2017-10-19 79 views
1

我目前正在尝试使用JavaScript中的原型来创建类继承,我理解如何在下面的简单示例中工作。JavaScript继承与父构造函数参数

var Person = function(){ 
    var name = "Steve"; 
} 

var Employee = function(){ 
    var company = "Stack Overflow"; 
} 

Employee.prototype = new Person; 

var employee1 = new Employee(); 

但现在假设我要添加参数的构造函数,这样我创建的对象,我可以设置的值。所以更新的代码是这样的:

var Person = function(initName){ 
    var name = initName; 
} 

var Employee = function(initName, initCompany){ 
    //How can I use initName to set the value in the prototype class? 

    var company = initCompany; 
} 

Employee.prototype = new Person; 

var employee1 = new Employee("Bob", "Intel"); 

我怎么能调用到人构造函数的名字吗?在C#中(我最熟悉的语言),你可以简单地调用基础构造函数,并通过必要的参数,但似乎并没有在javascript中有相同的模式。

供参考,这是它可能看起来像在C#:

public class Person 
{ 
    string name; 

    public Person(string initName) 
    { 
     name = initName; 
    } 
} 

public class Employee : Person 
{ 
    string company; 

    public Employee(string initName, string initCompany) : base(initName) 
    { 
     company = initCompany; 
    } 
} 

var employee1 = new Employee("Bob", "Intel"); 

免责声明:正如你所看到的,我主要是一个面向对象编程,但我目前在JavaScript工作,所以一些我从JavaScript的角度来看可能是非感性的,随时挑战我的假设是必要的。

+0

看到这个任务[https://stackoverflow.com/questions/4152931/javascript-inheritance-call-super-constructor-or-use-prototype-chain)离子。它拥有你正在寻找的所有东西 –

+0

请参阅[Answer](https://stackoverflow.com/questions/4152931/javascript-inheritance-call-super-constructor-or-use-prototype-chain)。它拥有你正在寻找的一切。 –

回答

1

标准ES5及以下

对于示例的具体情况,headmax's answer做你需要什么。然而,你在C#和其他语言中使用经典继承模型可能会在一般意义上(即经典继承)做到这一点,但这与JavaScript Prototype模型的相同方式是不可能的。你也许可以得到最接近使用组成,就像这样:

var Person = function(initName){ 
    var name = initName; 
} 

var Employee = function(initName, initCompany){ 
    var innerPerson = new Person(initName); 

    var company = initCompany; 
} 

var employee1 = new Employee("Bob", "Intel"); 

然后,添加任何功能,你想上镜或扩展Person类必须实现为直通Employee类来实现,即。在内部Person对象中调用相应的函数。无可否认,这远非实际的继承,但它可以近似于多态性之类的行为。

编辑

嗯,这是我以前关于完全忘了,但你可以使用call()apply()真正实现更多的继承行为一点。使用电话或应用可以让你在指定的上下文中运行的功能(包括对象的构造函数),这样你就可以在孩子的上下文中运行的父类的构造,就像这样:

var Person = function(initName){ 
    var name = initName; 
} 

var Employee = function(initName, initCompany){ 
    Person.call(this, initName); 
    var innerPerson = new Person(initName); 

    var company = initCompany; 
} 

var employee1 = new Employee("Bob", "Intel"); 

但是,如果你想能够访问Employee构造函数中的name属性和您在Employee中定义的任何其他函数,您需要将名称的作用域可见性从var name = ...更改为this.name = ...,以便在正在构建的对象的作用域中可见(这是this引用),而不是绑定到构造函数的作用域。有关所有此类应用的最佳示例,请参见here

ES6

由于采用了2015年的ECMAScript的,你现在可以在包裹语法糖,看起来更像是经典的继承类定义。但是你必须记住,这仍然是在原型继承下实现的,所以当JavaScript引擎实际执行代码时,或者像Babel这样的转换器重写它时,可能会出现类似于组合或call()/apply()的情况。

+0

好吧,听起来我可能无法做我想做的事情,但感谢使用合成的替代方法。除非有人给出更好的答案,否则我现在不得不继续这样做。如果他们不这样做,那么我会将你的标记标记为明天接受 –

+0

很高兴的作文可能会有所帮助,但我更新了答案,以包含其他一些可能有用且更像继承的方法 –

+0

优秀!使用Person.call并删除“var innerPerson”这一行,并将范围更改为“this ...”而不是“var ...”使我比任何其他方法都更接近我想要的内容,并且基本上覆盖了我想要的所有行为(特别是因为它允许我在子类中根据需要覆盖函数和属性) –

1

从ES6开始,JavaScript具有真实的类。他们不会在旧的浏览器(如Internet Explorer)中工作,但你可以写为

class Person { 
    constructor(name){ 
    this.name = name; 
    } 
} 

class Employee extends Person { 
    constructor(name, company) { 
    super(name); 
    this.company = company; 
    } 
} 
+0

是的,我希望我可以忽略旧的浏览器并使用这个实现,但不幸的是我必须支持旧版本的JS,所以我不能使用它。有没有办法在旧版本中做到这一点? –

+0

你可以看看babel repl,看看他们在做什么。这不是最漂亮的,但它绝对是你想要的。 https://babeljs.io/repl/ –

+0

谢谢,这是一个有用的工具。这绝对是一团糟,所以我想我现在可能会坚持使用Ananth的方法,因为它更容易维护 –