你能帮助澄清Javascript原型继承方法的调用吗?

时间:2015-07-07 02:30:53

标签: javascript

在这段代码中:

html {overflow-y: scroll;}

var Fruit = function() {} Fruit.prototype = { color: function () { console.log('Fruit color...') } } var Apple = function () {} Apple.prototype = new Fruit() Apple.prototype.constructor = Apple var a = new Apple() Apple.prototype = null // the question!!! a.color() 设置为Apple.prototype时,为什么实例null仍然可以调用a方法?

2 个答案:

答案 0 :(得分:9)

您在创建实例Apple.prototype之后更改a引用

此处更改引用并不会为现有实例更改它。

你也会找到

var a = new Apple();
Apple.prototype = {}; // some other object
a instanceof Apple; // false

即。因为我们已经改变了 Apple的继承链 a不再被视为 Apple

如果您尝试进行Foo.prototype = null检查,设置instanceof Foo会导致 TypeError

更改对象属性并不会将引用更改为该对象。例如

var foo = {},
    bar = foo;
foo.hello = 'world';
foo === bar; // true

更改对象本身确实会更改参考

foo = {hello: 'world'};
foo === bar; // false

或者以更接近于如何从实例引用原型的方式编写

var Foo = {}, // pseudo constructor
    bar = {},
    baz = {};
var fizz = {}; // fizz will be our pseudo instance

Foo.bar = bar;          // pseudo prototype
fizz.inherit = foo.bar; // pseudo inheritance
Foo.bar = baz;          // pseudo new prototype
fizz.inherit === foo.bar; // false, instance inheritance points elsewhere

设置继承链的当前最佳做法不是使用new,而是使用Object.create

Apple.prototype = Object.create(Fruit.prototype);

如果您需要在 Apple 实例上调用Fruit构造函数,那么您可以

function Apple() {
    // this instanceof Apple
    Fruit.apply(this);
    // ...
}

答案 1 :(得分:0)

我们必须了解线后面发生的事情

var a = new Apple();

JavaScript采用基于Prototype的编程作为其OOP风格。这意味着,它通过克隆以前的对象而不是通过实例化类来创建新对象。鉴于Gecko和Webkit JavaScript引擎,以下是“新”声明背后的内容:

var a = clone(Apple.prototype); // this is an analogy to memcpy() in C/C++
a.__proto__ = Apple.prototype; // useful for the instanceof checking
a.constructor = Apple; // a function
a.constructor(); // so "this" in the called function means "a"

现在, a.color Apple.prototype.color 都是对位于地址的同一函数的引用,例如 0xABCD 因为值 0xABCD 已从 Apple.prototype 复制到 a 。因此,调用 a.color()将与地址 0xABCD 相关联,它与 Apple.prototype 无关,因此您可以自由地将 Apple.prototype 指定为null。

事实证明上面的 clone()函数实际上是众所周知的 Object.create()函数。 Object.create()还包含 __ proto __ 属性的分配。