Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/432.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.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继承:父';s数组变量保留值_Javascript_Oop_Inheritance - Fatal编程技术网

Javascript继承:父';s数组变量保留值

Javascript继承:父';s数组变量保留值,javascript,oop,inheritance,Javascript,Oop,Inheritance,我在这里尝试在JavaScript中使用继承,发现在父类中存在由子类继承的数组值问题。以下代码是正常继承: var Parent = function() { this.list = []; }; var Child = function() {}; Child.prototype = new Parent; Child.prototype.constructor = Child; var obj1 = new Child; obj1.list.push("hello"); c

我在这里尝试在JavaScript中使用继承,发现在父类中存在由子类继承的数组值问题。以下代码是正常继承:

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"];
当我将新的子对象初始化到obj1并尝试使用值“hello”推送obj1.list时,obj1.list打印[“hello”]。。到目前为止还不错

当我执行上面的示例时,出现了问题,我尝试将新的子对象初始化为obj2,然后用值“再见”按obj2list,而obj2.list现在打印[“你好”,“再见”]。(请参见下面的代码:)

我在这里可能有一个误解,但是Parent中的list数组以某种方式保留了该值,我不知道为什么

这是一个很大的问题,因为如果我将父类重用到许多其他子类(如上述情况),如果父类将数组变量共享到其子类,那么该值也将共享到其他子类,这对我来说是意外的

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

--问题:--

有人能帮我找出为什么上例中的列表(父对象的数组变量
)保留值/共享子对象启动的值(在上述情况下,obj1obj2


如果您有另一个解决方案可以解决这个问题,那将非常感谢您,但我很高兴首先找到上面的问题。

当子对象具有从其prototype对象继承的属性时,真正发生的是子对象具有对包含该属性的prototype的引用。孩子没有自己的副本。因此,两个子对象都使用同一个数组,即您分配给
Child.prototype
的(一)
父对象上的数组

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

newparent()
为您提供以下信息:

+-----------------+ | Parent instance | +-----------------+ | list = [] | +-----------------+ +------------------+ | Child instance 1 | +------------------+ +-----------------+ | (prototype) |------->| Parent instance | +------------------+ +-----------------+ | list = [] | +-----------------+ 再次执行
new Child()
将为您提供另一个:

+------------------+ +------------------+ | Child instance 1 | | Child instance 2 | +------------------+ +------------------+ | (prototype) |---+ | (prototype) |---+ +------------------+ | +------------------+ | | | | | +-----------------+ +-------------------------+---->| Parent instance | +-----------------+ | list = [] | +-----------------+ …下面是JavaScript引擎在看到
obj.list
时所做的操作:

  • 查看
    obj
    是否有自己的名为
    list
    的属性。若否,则:
  • 查看
    obj
    的原型是否有自己的名为
    list
    的属性。若否,则:
  • 查看
    obj
    的原型的原型是否有自己的名为
    list
    的属性
  • 等等,直到我们的原型用完
  • 在您的情况下,由于
    obj
    没有自己的
    list
    属性,因此引擎会查找其原型(您分配给
    Child.prototype
    Parent
    实例),在本例中,该实例确实具有该属性。所以就用这个。它不是复制给孩子或任何东西,而是被使用的。当然,因为它是一个数组,在数组上推动某个东西实际上会把它推到数组上

    如果要将某个内容分配给
    obj.list
    ,则
    obj
    将获得其自己的
    list
    属性,从而打破链。所以把
    this.list=[]Child
    中的code>将为每个孩子提供自己的列表

    每当原型上有对象引用时,您就会看到这一点,其中对象是可以修改的类型(“可变”对象)。数组、日期、普通对象(
    {}
    ),regexp等等,它们都有状态,都可以修改,所以您可以看到它们。(
    String
    实例是不可变的,因此尽管发生了同样的情况,但您看不到任何效果,因为字符串无法更改。)


    对于基本体,虽然您继承了它们,但无法更改它们的状态(只能用具有不同状态的新基本体替换它们),因此您看不到相同的效果。因此,如果
    obj
    从其原型继承属性
    foo
    ,并且
    foo
    42
    alert(obj.foo)
    将从原型获得值并显示“42”。更改
    foo
    的唯一方法是说
    obj.foo=67
    或类似的-这使
    obj
    拥有自己的
    foo
    副本,与原型副本不同。(即使你使用像
    ++
    --
    这样的东西,例如
    ++obj.foo
    ,这也是正确的;它实际上被评估为
    obj.foo=obj.foo+1
    )。

    这里缺少的是
    父.list
    只被实例化一次;当您将其“原型”复制到
    Child.prototype
    中时

    在JavaScript中实例化“子类”不会自动调用父构造函数。因此,
    Child
    的所有实例将共享相同的数组实例

    修改
    Child
    的构造函数以调用父构造函数应该是治疗您疾病的良方:

    var Child = function() {
        Parent.call(this);
    };
    
    显然,你已经对这个主题有了一些了解,但如果你感兴趣,这里有一些关于这个主题的文章值得一读:


    因为两个实例都引用了与原型相同的
    实例,因此引用了相同的数组。这里有很多JavaScript OOP问题,您应该看看它们。可能的重复和您令人敬畏的ascii图形保证超过+1,但这是唯一的
    
    var obj = new Child();
    obj.list.push("foo");
    
    var Child = function() {
        Parent.call(this);
    };