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

您能帮助澄清Javascript原型继承方法调用吗?,javascript,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.pr

在这段代码中:

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
仍然可以调用
color
方法?

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

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

你还会发现

var a = new Apple();
Apple.prototype = {}; // some other object
a instanceof Apple; // false
i、 e.因为我们改变了苹果的继承链
a
不再被视为苹果

设置
Foo.prototype=null
将导致类型错误,如果您试图检查Foo的
实例


更改对象的属性不会更改对该对象的引用。e、 g

更改对象本身会更改引用

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
,而是使用

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

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

我们必须了解幕后发生了什么

var a = new Apple();
JavaScript采用基于原型的编程作为其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()还包括uuu proto_uuu属性的赋值。

是的,正如我们所知,如果我们添加
Apple.prototype
一些方法,例如
Apple.prototype.嗅觉=function(){…}
,它将更改现有实例。但是我们改变了苹果的prototype,will不会改变实例。实例和
Apple.prototype
引用相同的对象,那么当更改
Apple.prototype
值不会影响对象,也不会影响实例?@huang.xinghui-向原型添加方法不会更改实例,该方法通过
[[prototype]]提供给实例
chain。也许读过一些关于属性解析和原型链的文章。@RobG你可能会误解,我在set
Apple.prototype
null
之前添加了这个方法。像这样
var a=newapple();Apple.prototype.smose=function(){console.log('Apple-smose…');Apple.prototype=null//这个问题!!!a、 嗅觉()
它不克隆原型,而是存储对原型的引用。(只要引用存在,它就不会被GC’d,因此即使原始引用被销毁,它也会保留)
var a = new Apple();
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"