如何组合构造函数和原型属性

时间:2014-07-06 15:11:56

标签: javascript constructor prototype prototypal-inheritance object-properties

我试图了解原型的工作原理。我有这个例子:

function Person(name) {
    if (arguments.length > 0)
        this.init(name);
}

Person.prototype.init = function(name) {
    this.name = name();
}
Employee.prototype = new Person();

function Employee (name, id) {
    if (arguments.length > 0) {
        this.init(name);
        this.id = id;
     }
}

var employee = new Employee("frank",01);
alert(employee.name);//returns frank

我试图弄清楚如何组合前两个部​​分,并分配" init"函数构造函数中的属性。我有这个,但它没有任何回报:

function Person(name) {
    if (arguments.length > 0)
        this.init = function(name) {
    this.name = name;
        }
}
Employee.prototype = new Person();

function Employee (name, id) {
    if (arguments.length > 0) {
        this.init(name);
        this.id = id;
     }
}

var employee = new Employee("frank",01);
alert(employee.name);//returns nothing

我假设我在分配init时做错了什么,但我不知道是什么。将初始属性更改为

this.init(name) = function(name) {

也不起作用。

2 个答案:

答案 0 :(得分:2)

是否要将init-property名称从Employee传递给Person?

这样做是这样的:

// Create a constructor-function for your Person-Object.
function Person(name) {
    this.name = name;
}

// Create the constructor-function for an Employee-Object that extends Person
function Employee(name) {
   // Call the constructor-function from Person
   Person.call(this, name);
}

// Let the prototype of Employee be Person.prototype (Employee extends Person)
Employee.prototype = Object.create(Person.prototype);
// By changing the prototype of Employee we have lost our constructor-function Employee()
// so we have to recover it.
Employee.prototype.constructor = Employee;

也许您期望超级构造函数将被隐式调用,就像您可能从其他语言(如Java)中了解它一样。但这不会发生在JavaScript中。您必须通过调用

自行完成此操作
Person.call(this, name)

在MDN上有一个非常好的JavaScript-Tutorial帮助我理解原型的东西:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/A_re-introduction_to_JavaScript

查看“自定义对象”一章。我想我无法更好地解释它。

答案 1 :(得分:1)

在您的第二个代码段中,如果您稍微更改了一行

Employee.prototype = new Person('bob');

代码会工作(员工仍然是'坦白')

问题在于构造函数

function Person(name) {
    // create member 'init' ONLY if an argument was passed to the constructor
    if (arguments.length > 0)
        this.init = function(name) {
            this.name = name;
        }
}

正如在另一个答案中所说,更改Person的原型会更改班级Person的所有实例,并且

Person.prototype.init = function(name) { ... }

init的每个实例中创建成员函数Person。但是在你的构造函数中有一个条件,只有在有参数的情况下才会创建init

该行

Employee.prototype = new Person();

指出,类Employee的每个实例都将包含所有成员,右侧有一个对象。在这种情况下 - Person

的新实例

顺便说一下,不建议在类构造函数中定义函数成员,因为每次调用构造函数时,都需要创建一个新函数。而在修改原型的情况下,该函数只创建一次,并与对象的所有实例共享。