JavaScript中的原型链接

Joh*_*ino 8 javascript inheritance prototype reference chaining

我正在读一本名为JavaScript模式的书,但有一部分我觉得这个人很困惑.

这个家伙实际上在书中引出了klass设计模式,在那里他逐一开发了它.他首先提出了这个问题:

function inherit(C, P) {
C.prototype = P.prototype;
}
Run Code Online (Sandbox Code Playgroud)

他说:

"这为您提供了简短快速的原型链查找,因为所有对象实际上共享相同的原型.但这也是一个回顾,因为如果继承链中的某个子项或孙子修改原型,它会影响所有父母和祖父母."

但是,我实际上试图在Child中修改原型say()并且它对Parent没有影响,实际上Child仍指向Parent并且完全忽略了它自己的同名原型,这是有意义的,因为它指向不同的内存位置.那家伙怎么能这样说呢?以下证明了我的观点:

function Parent(){}

Parent.prototype.say = function () {
return 20;
};

function Child(){
}

Child.prototype.say = function () {
return 10;
};

inherit(Child, Parent);

function inherit(C, P) {
C.prototype = P.prototype;
 } 

 var parent = new Parent();
var child = new Child();


var child2 = new Child()
alert(child.say(); //20
alert(parent.say()); //20
alert(child2.say()); //20
Run Code Online (Sandbox Code Playgroud)

任何孩子或孙子都不可能修改原型!

这导致了我的第二点.他说,在继承链(我无法重现)中意外修改父原型的可能性问题的解决方案是打破父母和孩子原型之间的直接联系,同时从原型链中受益.他提供以下解决方案:

function inherit(C, P) {
var F = function () {};
F.prototype = P.prototype;
C.prototype = new F();
}
Run Code Online (Sandbox Code Playgroud)

问题是这输出与其他模式相同的精确值:

function Parent(){}

Parent.prototype.say = function () {
return 20;
};

function Child(){
}

 Child.prototype.say = function () {
return 10;
};

inherit(Child, Parent);

function inherit(C, P) {
var F = function () {};
F.prototype = P.prototype;
C.prototype = new F();
}

var parent = new Parent();
var child = new Child();


var child2 = new Child()
alert(child.say(); //20
alert(parent.say()); //20
alert(child2.say()); //20
Run Code Online (Sandbox Code Playgroud)

空函数以某种方式打破链接是没有意义的.实际上,Child指向F和F依次指向Parent的原型.所以他们仍然指向相同的记忆位置.这在上面说明,它输出与第一个例子相同的精确值.我不知道这位作者试图证明什么,以及为什么他提出不为我凝胶并且我无法复制的说法.

谢谢你的回复.

Har*_*men 8

对你来说第一点:

这个人试图说的是,如果创建实例修改原型,则子对象和父对象的方法都会改变.

例如:

function inherit(C, P) {
  C.prototype = P.prototype;
} 

function Parent(){}
function Child(){}

inherit(Child, Parent);

Parent.prototype.say = function () {
  return 20;
};

var parent = new Parent();
var child = new Child();


// will alert 20, while the method was set on the parent.
alert( child.say() );
Run Code Online (Sandbox Code Playgroud)

更改子项的构造函数(与父项共享)时会发生同样的事情.

// same thing happens here, 
Child.prototype.speak = function() {
  return 40;
};

// will alert 40, while the method was set on the child
alert( parent.speak() );
Run Code Online (Sandbox Code Playgroud)

关于你的第二点:

function inherit(C, P) {
  var F = function () {};
  F.prototype = P.prototype;
  C.prototype = new F();
}
Run Code Online (Sandbox Code Playgroud)

新的继承函数实际上将父项的构造函数与子项分开,因为它不再指向同一个对象,但现在它指向一个与父项无关的新创建函数的原型.因此,您实际上创建了父构造函数的本地副本,然后创建了一个新的副本实例,它将所有构造函数方法返回一个属性.通过现在更改子项的构造函数,它不会影响父项.

function inherit(C, P) {
  var F = function () {};
  F.prototype = P.prototype;
  C.prototype = new F();
}

function Parent(){}
function Child(){}

inherit(Child, Parent);

// same thing happens here, 
Child.prototype.speak = function() {
  return 40;
};

var parent = new Parent();

// will throw an error, because speak is undefined
alert( parent.speak() );
Run Code Online (Sandbox Code Playgroud)