javascript原型继承 [英] javascript prototype inheritance

查看:115
本文介绍了javascript原型继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这似乎不一致,但可能是因为我是javascript原型继承功能的新手。

This seems inconsistent, but probably is due to the fact that I'm new to javascript's prototype inheritance feature.

基本上,我有两个基类属性,list和name。我实例化两个子类并为属性赋值。当我实例化第二个子类时,它从第一个子类实例获取列表值,但仅用于列表而不用于名称。这是怎么回事??当然,我希望任何后续的子类实例都不会从其他实例获取值,但如果发生这种情况,它应该是一致的!

Basically, I have two base class properties, "list" and "name". I instantiate two subclasses and give values to the properties. When I instantiate the second subclass, it gets the list values from the first subclass instance, but only for the "list" and not for "name". What's going on?? Of course, I would prefer that any subsequent subclass instances not get values from other instances, but if that's going to happen, it should be consistent!

这是一段代码片段:

    function A()
    {
        this.list = [];
        this.name = "A";
    }
    function B()
    {
    }
    B.prototype = new A();

    var obj1 = new B();
    obj1.list.push("From obj1");
    obj1.name = "obj1";

    var obj2 = new B();

    //output:
    //Obj2 list has 1 items and name is A
    //so, the name property of A did not get replicated, but the list did
    alert("Obj2 list has " + obj2.list.length + " items and name is "+ obj2.name);    


推荐答案

有原型的东西,就是你可以读取他们整天都在这里,它不会改变指向什么的底层结构。但是,第一次执行作业时,您将在那个实例上替换该属性指向的内容。

The thing with prototypes, is that you can do reads all day long from them, and it wont change the underlying structure of what is pointing to what. However, the first time you do an assignment, you are replacing, on that instance, what that property points to.

在您的情况下,你没有真正重新分配prototyped属性,你修改了在该属性中找到的底层结构的值。

In your case, you didn't actually reassign the prototyped property, you modifed the value of the underlying structure that was found at in that property.

这意味着共享的所有对象A的原型实际上共享 A的实现。这意味着在A的所有实例中都可以找到A中携带的任何状态。当你在B的实例上对该属性进行赋值时,你已经有效地替换了那个实例(并且只有那个实例)指向的东西(我相信这是因为B上有一个新的属性name,它在范围链中被命中,然后才到达name实现A)。

What this means is that all objects that share a prototype of A actually share the implementation of A. That means any state carried in A will be found on all instances of B. The moment you do an assignment to that property on an instance of B, you have effectively replaced what that instance (and only that instance) points to (I believe this is due to the fact there is a new property "name" on B that gets hit in the scope chain, before it reaches the "name" implementation on A).

编辑:

为了更详细地说明最新情况:

To give a more explicit example of whats going on:

B.prototype = new A();
var obj1 = new B();

现在,我们第一次读取时,解释器会执行以下操作:

Now, the first time we do a read, the intepreter does something like this:

obj1.name;

翻译:我需要属性名称。首先,检查B. B没有'名称',让我们继续沿着范围链继续。接下来,A。Aha!A有'名字',返回

Interpreter: "I need property name. First, check B. B does not have 'name', so lets continue down the scope chain. Next up, A. Aha! A has 'name', return that"

但是,当你写作时,翻译不会实际上关心的是继承的财产。

However, when you do a write, the interpreter doesn't actually care about the inherited property.

obj1.name = "Fred";

翻译:我需要分配属性'name'。我在这个范围内B的实例,所以将'Fred'分配给B.但是我将其他所有内容都放在范围链的更远处(即A)

Interpreter: "I need to assign to property 'name'. I'm within the scope of this instance of B, so assign 'Fred' to B. But I leave everything else farther down the scope chain alone (i.e., A)"

现在,下次你阅读...

Now, next time you do a read...

obj1.name;

翻译:我需要财产'名称'。啊哈!这个实例 B的属性'name'已经就位于它上面。只需返回 - 我不关心范围链的其余部分(即A.name)

Interpreter: "I need property 'name'. Aha! this instance of B has the property 'name' already sitting on it. Just return that - I don't care about the rest of the scope chain (i.e. A.name)"

因此,第一次写入name时,它会将其作为第一个类属性插入到实例上,并且不再关心AAname上的内容仍然存在,它只是向下范围链和JS解释器在找到它想要的东西之前没有那么远。

So, the first time you write to name, it inserts it as a first class property on the instance, and doesn't care anymore about what is on A. A.name is still there, it's just further down the scope chain, and the JS interpreter doesn't get that far before it found what it was looking for.

如果name在A中有一个默认值(如你有,这是A),那么你会看到这种行为:

If "name" had a default value in A (as you have, which is "A"), then you would see this behaviour:

B.prototype = new A();
var obj1 = new B();
var obj2 = new B();

obj1.name = "Fred";

alert(obj1.name); // Alerts Fred
alert(obj2.name); // Alerts "A", your original value of A.name

现在,就你而言对于数组,您实际上从未使用新数组替换列表。你做的是抓住数组本身的一个句柄,并添加一个元素。因此,B的所有实例都受到影响。

Now, in the case of your array, you never actually replaced list on the scope chain with a new array. What you did is grab a handle on the array itself, and added an element to it. Hence, all instances of B are affected.

翻译:我需要获得'list'属性,并添加一个元素。检查B的这个例子... nope,没有''列表'属性。下一个在范围链中:A。是的,A有'列表',使用它。现在,按下列表

Interpreter: "I need to get the 'list' propery, and add an element to it. Checking this instance of B ... nope, does not have a 'list' property. Next in the scope chain: A. Yep, A has 'list', use that. Now, push onto that list"

这将如果你这样做不是

obj1.list = [];
obj1.push(123);

这篇关于javascript原型继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆