这是JavaScript的原型继承模型中的缺陷吗?

时间:2013-08-26 00:57:35

标签: javascript inheritance prototypal

我一直在学习JavaScript中的原型继承来自John Resig的 JavaScript Ninja的秘密,我想知道下面的代码示例(我刚刚编写的)会发生什么。

function Person() {}

Person.prototype.sayHello = function() {
    alert("Hello World");
}

function Ninja() {}

Ninja.prototype.swingSword = function() {
    alert("I can swing my sword.");
}

Ninja.prototype = new Person();

var ninja1 = new Ninja();

据我所知,所有这些代码行的结果是变量ninja1引用了一个Ninja对象,通过其原型,它具有swingSword方法,通过Person原型的原型继承,有sayHello方法。

我感到困惑的地方如下:因为属性swingSword(恰好是一个方法)附加到Ninja的原型之前人员实例被分配给Ninja的原型,swingSword属性/方法不会被后来的Person实例赋值覆盖吗?如果没有,那么引用原型对象的Ninja原型属性如何引用Person实例,都有swingSword属性?

1 个答案:

答案 0 :(得分:4)

  

[...]通过它的原型,有swingSword方法,[...]

虽然该陈述的其余部分是正确的 - ninja1引用Ninja(从技术上讲,Ninja.prototype)并且将通过继承进行sayHello - 您的关于swingSword以后的想法是正确的。

  

swingSword实例的后期分配不会覆盖Person属性/方法吗?

在您的代码段末尾,ninja1.swingSword应为undefined

console.log(typeof ninja1.swingSword); // 'undefined'

// as is:
console.log(typeof Ninja.prototype.swingSword); // 'undefined'

Ninja.prototype = ...之后,prototype所附加的原始swingSword对象不再被引用。因此,在创建新实例时不会使用它。


如果您打算设置一个新的prototype对象,您需要在修改之前确保已完成。

Ninja.prototype = new Person();

Ninja.prototype.swingSword = function() {
    alert("I can swing my sword.");
}

var ninja1 = new Ninja();

console.log(typeof ninja1.swingSword); // 'function'

而且,如果ninja1确实有swingSword,则可能意味着它是在prototype更改之前创建的。

对象在创建时保留自己的[[Prototype]] reference,无论可能对其构造函数的prototype属性进行哪些更改。

Ninja.prototype.swingSword = function() {
    alert("I can swing my sword.");
}

var ninja1 = new Ninja();

Ninja.prototype = new Person(); // won't affect existing instances

var ninja2 = new Ninja();

console.log(typeof ninja1.swingSword); // function
console.log(typeof ninja2.swingSword); // undefined

每个例子:http://jsfiddle.net/G8uTk/