Javascript继承:Parent的数组变量保留值 [英] Javascript Inheritance: Parent's array variable retains value

查看:92
本文介绍了Javascript继承:Parent的数组变量保留值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在JavaScript中使用继承,并且我发现在类继承的 Parent 类中具有数组值的问题。下面的代码是正常继承:

I'm trying to use inheritance in JavaScript here, and I found problem having array value in Parent class that is inherited by a Child class. Below code is normal inheritance:

var Parent = function() {
    this.list = [];
};

var Child = function() {};

Child.prototype = new Parent;
Child.prototype.constructor = Child;

var obj1 = new Child;

obj1.list.push("hello");

console.log(obj1.list); // prints ["hello"];

当我初始化新的 Child 对象时(继承包含名为的数组变量的Parent) 列出)到 obj1 ,并尝试将 obj1.list 推送到值hello, obj1.list 打印[你好] ..到目前为止一直很好。

When I initialized new Child object (inherits Parent which contains array variable named list) to obj1 and tried to push obj1.list with a value "hello", obj1.list prints ["hello"] .. so far so good.

当我做上面的例子而我试图初始化新的孩子时出现问题反对 obj2 然后按 obj2 列表并输入值goodbye,然后 obj2.list 打印[你好再见]。 (见下面的代码:)

The problem comes when I did the above example and I tried to initialize new Child object to obj2 then push obj2's list with a value "goodbye", and obj2.list now prints ["hello", "goodbye"]. (See the code below:)

var obj2 = new Child;

obj2.list.push("goodbye");

console.log(obj2.list); // prints ["hello", "goodbye"];

我可能会有误解,但列表数组在父母以某种方式保留了价值,我不知道为什么。

I might have a misconception here, but the list array in Parent is somehow retaining the value and I don't know why.

这是一个很大的麻烦,因为如果我重用

类到许多其他子类,如上面的情况,如果 Parent 将数组变量共享到其子类,则该值也将共享给其他子类,这对我来说是意料之外的。

This is a big trouble because if I reuse the Parent class to many other child classes like the case above, if Parent has array variable shared to its child classes, the value will be shared to the other child classes as well, which is unexpected for me.

我所期望的是, Child 类代表新对象,当时, Parent 类也是如此子类初始化为 obj1 ,然后当我将 Child 对象初始化为 obj2 时,的推送值obj1 不应与 obj2 共享。

What I expected is, the Child class represents new object, same goes to Parent class when Child class is initialized to obj1, which then when I initialize new Child object to obj2, the pushed value from obj1 should not be shared with obj2.

- 问题 -

任何人都可以帮我找出为什么列表(上例中的数组变量)保留值/共享由Child对象启动的值(在上例中, obj1 obj2 )?

Can anyone help me find out why the list (the array variable of Parent) in the example above retains the values/share the values that are initiated by the Child objects (in above case, obj1 and obj2)?

如果你有另一个解决方案可以解决这个问题,那将是非常好的,但我会很高兴找到上面的问题第一个。

If you have another solution that could solve this problem, it will be very nice of you, but I'll be happy to find out the problem above first.

推荐答案

当子对象具有从其原型对象继承的属性时,真正发生的是孩子有一个引用到原型,其中包含属性。孩子没有自己的副本。所以两个孩子都使用相同的阵列—您已分配给 Child.prototype 的(一) Parent 原型对象上的那个。

When a child object has a property inherited from its prototype object, what's really happening is that the child has a reference to the prototype, which contains the property. The child doesn't have its own copy of it. So both children are using the same array — the one on the (one) Parent prototype object you've assigned to Child.prototype.

首先是一些图片,然后是更多文字。 : - )

First some pictures, then more text. :-)

new Parent()给你:

+-----------------+
| Parent instance |
+-----------------+
| list = []       |
+-----------------+

...然后你分配给 Child.prototype

...which you then assign to Child.prototype.

然后, new Child()给你这个:

+------------------+
| Child instance 1 |
+------------------+        +-----------------+
| (prototype)      |------->| Parent instance |
+------------------+        +-----------------+
                            | list = []       |
                            +-----------------+

新孩子()再次给你另一个:


+------------------+      +------------------+
| Child instance 1 |      | Child instance 2 |
+------------------+      +------------------+
| (prototype)      |---+  | (prototype)      |---+
+------------------+   |  +------------------+   |
                       |                         |
                       |                         |     +-----------------+
                       +-------------------------+---->| Parent instance |
                                                       +-----------------+
                                                       | list = []       |
                                                       +-----------------+

所以你可以看到,所有的实例共享相同的 Parent 实例(他们的原型),它有一个数组在它上面。

So as you can see, all of the Child instances are sharing the same Parent instance (their prototype), which has an array on it.

当你说:

var obj = new Child();
obj.list.push("foo");

...这是JavaScript引擎在看到 obj.list时的作用

...here's what the JavaScript engine does when it sees obj.list:


  1. 查看 obj 是否有其自己的属性名为 list 。如果没有,那么:

  2. 查看 obj 的原型是否有拥有的属性列表。如果没有,那么:

  3. 看看 obj 的原型的原型是否有自己的属性被调用 list

  4. 等。直到我们用完原型。

  1. Looks to see if obj has its own property called list. If not, then:
  2. Looks to see if obj's prototype has its own property called list. If not, then:
  3. Looks to see if obj's prototype's prototype has its own property called list.
  4. Etc. until we run out of prototypes.

在你的情况下,因为 obj 没有没有拥有 列表属性,引擎会查看其原型( Parent 您分配给 Child.prototype 的实例,在这种情况下确实具有该属性。所以使用了一个。它不会复制到孩子或任何东西,它是使用。当然,因为它是一个数组,所以在数组上推送一些东西实际上会把它推到数组上。

In your case, since obj doesn't have its own list property, the engine looks to its prototype (the Parent instance you assigned to Child.prototype), which in this case does have the property. So that one is used. It's not copied to the child or anything, it's used. And of course, since it's an array, pushing something on the array actually pushes it onto the array.

如果你要分配的东西到 obj.list ,然后 obj 将获得拥有 列表属性,打破了链条。因此将 this.list = []; 放在 Child 中会为每个孩子提供自己的列表。

If you were to assign something to obj.list, then obj would get its own list property, breaking the chain. So putting this.list = []; in Child would give each child its own list.

只要原型上有对象引用,你就会看到这个,其中对象是一个可以修改的类型(一个可变对象) 。数组,日期,普通对象( {} ),RegExps等,它们都有状态,它们都可以被修改,所以你可以看到它们。 ( String 实例是不可变的,所以尽管发生了同样的事情,但是没有看到它的任何影响,因为无法更改字符串。)

You'll see this any time a prototype has an object reference on it, where the object is a type that can be modified (a "mutable" object). Arrays, Dates, plain objects ({}), RegExps, etc., they all have state and they can all be modified, so you'd see it with them. (String instances are immutable, so although this same thing happens, you don't see any effect from it because the string cannot be changed.)

对于原语,虽然你继承它们,但是你不能改变它们的状态(你只能用一个具有不同状态的新原语替换它们),所以你不要看到同样的效果。因此,如果 obj 从其原型继承属性 foo ,并且 foo 42 alert(obj.foo)将从原型中获取值并显示42。更改 foo 的唯一方法是说 obj.foo = 67 或类似的 —它给 obj c c c c>的自己的副本,与原型的副本不同。 (即使你使用像 ++ - 这样的东西也是如此,例如 + + obj.foo ;它实际上被评估为 obj.foo = obj.foo + 1 )。

With primitives, although you inherit them, you can't change their state (you can only replace them with a new primitive with a different state), so you don't see this same effect. So if obj inherits the property foo from its prototype, and foo is 42, alert(obj.foo) will get the value from the prototype and show "42". The only way to change foo is to say obj.foo = 67 or similar — which gives obj its own copy of foo, distinct from the prototype's copy. (This is true even if you use things like ++ and --, e.g. ++obj.foo; that really gets evaluated as obj.foo = obj.foo + 1).

这篇关于Javascript继承:Parent的数组变量保留值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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