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

hua*_*hui 6 javascript

在这段代码中:

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()
Run Code Online (Sandbox Code Playgroud)

何时Apple.prototype设置为null,为什么实例a仍然可以调用该color方法?

Pau*_* S. 9

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

此处更改引用不会更改现有实例的引用.

你也会发现

var a = new Apple();
Apple.prototype = {}; // some other object
a instanceof Apple; // false
Run Code Online (Sandbox Code Playgroud)

即因为我们改变了Apple 的继承链,a不再被认为是Apple.

如果您尝试进行检查,设置Foo.prototype = null将导致TypeErrorinstanceof Foo


更改属性的的对象不改变引用对象.例如

var foo = {},
    bar = foo;
foo.hello = 'world';
foo === bar; // true
Run Code Online (Sandbox Code Playgroud)

更改对象本身会更改引用

foo = {hello: 'world'};
foo === bar; // false
Run Code Online (Sandbox Code Playgroud)

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

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
Run Code Online (Sandbox Code Playgroud)

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

Apple.prototype = Object.create(Fruit.prototype);
Run Code Online (Sandbox Code Playgroud)

如果你需要FruitApple实例上调用的构造函数,你会这样做

function Apple() {
    // this instanceof Apple
    Fruit.apply(this);
    // ...
}
Run Code Online (Sandbox Code Playgroud)