简体   繁体   English

javascript - 结合两个构造函数

[英]javascript - combining two constructors

I'm trying to extend one constructor with another, using prototype: 我正在尝试使用原型扩展一个构造函数和另一个构造函数:

var objA = function(name){

    var obj = this; 

    this.test.name = name;

    window.setTimeout(function(){
        console.log(obj.test.name)
    }, 1)

}

var objB = function(name){

    this.name = 'test'


}

objA.prototype.test = new objB();

var a = ['A', 'B', 'C', 'D']

for(var i = 0; i < a.length; i++){
   new objA(a[i])
}

This approach works great for one object, but if ( as in this example ) i want to create multiple, it seems that the last entry ( 'D' ) overwrites previous, because in all 4 cases obj.test.name returns D . 这种方法适用于一个对象,但如果(如本示例中)我想创建多个,似乎最后一个条目('D')会覆盖之前的条目,因为在所有4个案例中obj.test.name返回D Maybe someone could point out what i'm doing wrong, or maybe other solution for this case. 也许有人可以指出我做错了什么,或者可能是其他解决方案。 Thanks. 谢谢。

JavaScript implements inheritance through chaining objects. JavaScript通过链接对象实现继承。 objA has a prototype property test which is an instance of objB . objA有一个原型属性test ,它是objB一个实例。 This is shared to all instances of objA 这与objA所有实例共享

objA.prototype.test = new objB();

Now in your constructor for objA , it modifies objA.prototype.test which is shared across all instances of objA . 现在,在您的构造函数objA ,它修改objA.prototype.test这是跨越的所有实例共享objA This means that all instances of objA will have a value of "D" since the last iteration makes the shared property hold "D". 这意味着objA所有实例objA将具有值“D”,因为最后一次迭代使共享属性保持为“D”。

If you want to hold a unique name property for each instance, you need to attach it to the instance , not the shared parent. 如果要为每个实例保留唯一的name属性,则需要将其附加到实例 ,而不是共享父项。

var objA = function (name) {
  this.name = name;
}

Now, you seem to notice that there is name on both instance, and the shared parent. 现在,您似乎注意到实例和共享父级都有name Well, JS reads from the instance first. 好吧,JS首先从实例中读取。 If it sees a property name , it takes it's value from there. 如果它看到属性name ,则从那里获取它的值。 If not, it reads from the shared parent, where it defaults to 'test'. 如果没有,它从共享父节点读取,默认为“test”。

It can be seen here , where I made a minor console.log on them. 在这里可以看到 ,我在其上制作了一个次要的console.log You can see that the value has 2 name properties, one on the instance, on on the parent, but it reads the instance's value first. 您可以看到该值具有2个名称属性,一个在实例上,在父项上,但它首先读取实例的值。

Prototype is like static functions, all instances share one so all instances of objA share a test property that points to the same instance of objB Prototype就像静态函数一样,所有实例共享一个,所以objA的所有实例共享一个指向objB的同一个实例的test属性

Normally assigning new values to a property would set that value for the the instance property: Prototypical inheritance - writing up 通常,为属性分配新值将为实例属性设置该值: 原型继承 - 编写

In this case you assing a value to a property of the prototype and not the prototype so it'll assign a new value for all instances. 在这种情况下,您为原型的属性而不是原型赋值,因此它将为所有实例分配新值。

var objA = function(name){
    var obj = this; 
    this.test.name = name;
    console.log("this.name.is:",this.test.name);
}

var objB = function(name){
    this.name = 'test'
}
objA.prototype.test = new objB();
objA.prototype.arr=[];

var a = ['A', 'B', 'C', 'D']
var arr=[];
for(var i = 0; i < a.length; i++){
   arr.push(new objA(a[i]))
}
console.log(arr[0].test.name)
arr[0].arr.push("pushed in 0");
console.log(arr[1].arr);
arr[0].arr=["assigned in 0"];
console.log(arr[1].arr);
arr[0].test.name="assigned in 0";
console.log(arr[1].test.name);

Your problem is setTimeout. 你的问题是setTimeout。 You're creating an event handler that runs on the last known information, in this case, when the function is passed 'D'. 你正在创建一个事件处理程序,它运行在最后的已知信息上,在这种情况下,当函数传递给'D'时。 Without setTimeout, it gives the right values. 没有setTimeout,它会给出正确的值。

You probably want to wrap new objA(a[i]) in a setTimeout instead. 您可能想要在setTimeout中包装新的objA(a [i])。

window.setTimeout(function(a){   
 new objA(a[i]);
}(a), 1);

Because of closures. 因为封闭。

您应该在原型中创建“createTest”函数而不是“test”对象

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM