JavaScript,设置“原型”时使用和不使用“新”之间的区别

时间:2013-11-17 12:49:40

标签: javascript prototypal-inheritance

如果我在Firefox中运行这段JavaScript代码:

function Human() {

}

function Engineer(diploma) {
    this.diploma = diploma;
}

Engineer.prototype = new Human();// Line A1
Engineer.prototype.constructor = Engineer;
Engineer.prototype.getDiploma = function() {
    alert(this.diploma);
};
var engineer = new Engineer("Bridges and Roads");
engineer.getDiploma();
var human = new Human();
human.getDiploma(); // Line A2

标记为“A2”的行将在Firefox控制台中生成错误:

TypeError: human.getDiploma is not a function

另请注意,在A1行,我使用“new”来模拟Engineer继承自Human。这可以在以下JSFiddle中测试:

http://jsfiddle.net/RMWdh/1/

现在我像这样改变A1线:

function Human() {

}

function Engineer(diploma) {
    this.diploma = diploma;
}

Engineer.prototype = Human.prototype;// Line B1
Engineer.prototype.constructor = Engineer;
Engineer.prototype.getDiploma = function() {
    alert(this.diploma);
};
var engineer = new Engineer("Bridges and Roads");
engineer.getDiploma();
var human = new Human();
human.getDiploma(); // Line B2

请注意,A1线已被B1线替换。其余的代码是一样的。这一次,如果我运行它,Firefox控制台中没有错误,但我会收到一条警告“Bridges and Roads”(这是对engineer.getDiploma()的调用),另一条警告说“undefined”(其中是B2线的结果)。这也可以在JSFiddle上查看,这里:

http://jsfiddle.net/RMWdh/2/

我的问题是:为什么会出现这种差异?这样做有什么区别:

 Engineer.prototype = new Human();

和此:

 Engineer.prototype = Human.prototype;

2 个答案:

答案 0 :(得分:3)

后者只是复制引用,使“工程师是人类”和“人类是工程师”都是真的。这通常不是预期的效果。

Engineer.prototype = Human.prototype;
var human = new Human();
/*
  engineer ->
    (Engineer.prototype & Human.prototype) ->
      Object.prototype
*/

var human = new Human();
console.log('getDiploma' in human);     // true
console.log(human instanceof Engineer); // true

另一方面,前者仅确定“工程师是人类”。这允许Engineer将自己的身份和逻辑与其他Human分开。在这种情况下,包括.getDiploma()

Engineer.prototype = new Human();
var engineer = new Engineer("Bridges and Roads");
/*
  engineer ->
    Engineer.prototype ->
      Human.prototype ->
        Object.prototype
*/

var human = new Human();
console.log('getDiploma' in human);     // false
console.log(human instanceof Engineer); // false

您还可以使用Object.create()建立prototype chain,而无需调用构造函数:

Engineer.prototype = Object.create(Human.prototype);

答案 1 :(得分:0)

你的问题是原型继承:

你要拨打的是A2线

human.getDiploma()

但是getDiploma没有出现在Human的原型上。

工程师继承对象Human作为它的原型,但Human不会继承工程师的任何东西。

如果你将getDiploma()作为Human的一个方法,你就可以了:

function Human() {

}

Human.prototype.getDiploma = function() {
    alert(this.diploma);
};

function Engineer(diploma) {
    this.diploma = diploma;
}

Engineer.prototype = Human.prototype;// Line B1
Engineer.prototype.constructor = Engineer;

var engineer = new Engineer("Bridges and Roads");
engineer.getDiploma(); // "Bridges and Roads"
var human = new Human();
human.getDiploma(); // "undefined"