Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/469.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何使用链式javascript原型继承?_Javascript_Prototype_Scope_This_Prototyping - Fatal编程技术网

如何使用链式javascript原型继承?

如何使用链式javascript原型继承?,javascript,prototype,scope,this,prototyping,Javascript,Prototype,Scope,This,Prototyping,我很难在javascript中设置原型继承。理想情况下,我希望thing1和thing2都有自己的“新实体原型”的干净副本 我想避免使用这个 [编辑] 我大致知道这是怎么回事 设置thing1.b设置Thing实例的b属性。不接触原型链中定义的实体.b 其中,无法在Thing实例上设置thing1.a.a,因为它将抛出“cannotset a on undefined”错误。这就是它在原型链上查找Entity.a的时候,Entity.a被定义并将Entity.a.a设置为一个新值 [进一步编辑]

我很难在javascript中设置原型继承。理想情况下,我希望thing1和thing2都有自己的“新实体原型”的干净副本

我想避免使用
这个

[编辑]

我大致知道这是怎么回事

设置thing1.b设置Thing实例的b属性。不接触原型链中定义的实体.b

其中,无法在Thing实例上设置thing1.a.a,因为它将抛出“cannotset a on undefined”错误。这就是它在原型链上查找Entity.a的时候,Entity.a被定义并将Entity.a.a设置为一个新值

[进一步编辑]


正如@IvoWetzel所说,设置thing1.b不会触及原型链,因为设置属性不会。其中,设置thing1.a.a执行两个步骤。thing1.A上的一个getter,它接触到原型链,然后是一个setter of.A

您可以做的一件事是在
thing
中应用
实体的
构造函数的逻辑,例如:

function Entity() {
    this.a = {a: 4};
    this.b = 5;
}

function Thing() {}
Thing.prototype = new Entity;

var thing1 = new Thing;
thing1.a.a = 3;
thing1.b = 4;
var thing2 = new Thing;
console.log(thing2.a.a); // prints 3 instead of 4. I would like 4.
console.log(thing2.b) // prints 5 as wanted

这是因为JavaScript对象始终被视为引用

因此,当您通过执行
a.a.a=3更改
this.a
对象时您正在更改内存中的一个对象。
Thing
的新实例将引用内存中的同一对象,因为并非每次调用
Thing
时都调用
实体
构造函数,而
对象保持不变


我会把
this.a
放在原型链之外,很可能直接放在
东西
构造函数里面。这将使得每次实例化
东西时都会在内存中创建
This.a的新版本。

当CMS发布解决方案时,为什么
thing2.b
返回5,为什么
thing2.a.a
解析到对象

function Entity() {
    this.a = {a: 4};
    this.b = 5;
}
Entity.prototype.c = 6;

function Thing() {
  Entity.apply(this, arguments); // ejecutes the assignments made in Entity
}
Thing.prototype = new Entity;

var a = new Thing;
a.a.a = 3;

var b = new Thing;
console.log(a.a.a); // 3
console.log(b.a.a); // 4

console.log(a.b);   // 5
console.log(b.b);   // 5

console.log(a.c);   // 6
console.log(b.c);   // 6
var thing1=新事物;
//thing1没有a,但原型有a,因此a.a本质上是实体的a
事物1.a.a=3;
//在东西1上设置b,设置不在原型链上(!)
事物1.b=4;
//这就是事情的样子
事物{proto:Entity{

a:{这.a在实体构造函数中。请使用不太容易混淆的变量名好吗?也许不要对成员变量和全局变量重复使用a和b。尝试使用foo、bar、baz或其他方法。我使用了更合理的方法。可能是明智的。这解决了问题,但没有解释为什么a.a.a引用了新实体对象中的某个对象,其中S.A.A.A.B引用新事物Objo中的一些东西,你认为OP要求原型像类一样,那么OP应该调用超类构造函数是有意义的,这是等价的。确实如此;在 .A.<代码>中,你在一个对象内设置一个值,所以对象是共享的。,而使用
.b
您正在重新分配值。这是几乎所有语言中常见的标准引用和按值内容。以这种方式调用super是正确的方法。因此,还要注意,在构建Thing.prototype时,您正在调用实体构造函数;如果它不应该运行两次,您应该执行一些操作类似这样:
function tmp(){};tmp.prototype=Entity.prototype;Thing.prototype=new tmp()
。这是公共库中使用的技术,因为它在保持原型链正确的同时避免了构造函数调用(同样,因为
.prototype
东西是通过引用的,而不是通过值)@Raynos:不要做
Thing.prototype=Entity.prototype
-那么原型将是同一个对象。这就是为什么要使用
Thing.prototype=new tmp()
。你不想
Thing.prototype.a=1
影响
Entity.prototype.a
!为什么a.a.a不在东西上设置a.a?这是我真正想知道的。
var thing1 = new Thing;

// thing1 has no a, but the prototype has so a.a is essentially the a of Entity
thing1.a.a = 3;

// Sets b on thing1, setting does not go up the prototype chain(!)
thing1.b = 4;  

// that's what thing1 looks like
Thing {proto: Entity { 
                      a: { <--- gets resolved 
                          a: 3 <-- gets set
                      }, 
                      b: 5
              },
              b: 4 <-- gets set directly
      }


var thing2 = new Thing;

// thing2.a does not exist, so we look up the prototype and find a on Entity
console.log(thing2.a.a); 

// thing2.b also does not exists, so once again we look up the prototype to find b on Entity
console.log(thing2.b);

// that's what thing2 looks like
Thing {proto: Entity {
                      a: {
                          a: 3 <- gets resolved
                      },
                      b: 5 <- gets resolved
              }
      }