Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/380.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_Google Chrome_Inheritance - Fatal编程技术网

这是我在使用Javascript原型继承时应该看到的行为吗?

这是我在使用Javascript原型继承时应该看到的行为吗?,javascript,google-chrome,inheritance,Javascript,Google Chrome,Inheritance,我是Javascript新手,对如何使用继承有疑问 这篇文章到目前为止很有帮助,但我在Chrome调试器中观察到的行为似乎与我期望看到的不匹配 我有两个案子: Base = function () { this.value = 0; }; Base.prototype.constructor = Base; Derived = function () { Base.call(this); }; Derived.prototype = new Base(); Derived.

我是Javascript新手,对如何使用继承有疑问

这篇文章到目前为止很有帮助,但我在Chrome调试器中观察到的行为似乎与我期望看到的不匹配

我有两个案子:

Base = function () {
    this.value = 0;
};

Base.prototype.constructor = Base;

Derived = function () {
    Base.call(this);
};

Derived.prototype = new Base();
Derived.prototype.constructor = Derived;
在调试器中,我看到以下内容:

在完成作业后,我看到了这一点

实例中的值已更改,但原型中的值未更改。这是意料之中的事吗

我不太理解的第二种方法是这里再次引用了这一点——请参阅“重新访问属性继承”一节底部截取的代码

Base = function () {
};

Base.prototype.constructor = Base;
Base.prototype.value = 0;

// Derived as before...
任务结束后呢

值已作为新属性添加。这不应该改变原型中的值吗?或者我是否明确需要通过原型访问该值-例如,派生的.value.prototype.value=5

如果您有任何关于这方面的信息,我们将不胜感激

谢谢

更新:

感谢所有回复的人,事实证明这与我没有在适当的时间使用Object.create有关。我将代码更新为:

在调试器中,我得到了我所期望的:

这看起来不错


感谢@sixfingeredman和@Bergi对您的帮助

首先,当不在主题上时,删除此行:

Base.prototype.constructor = Base;
它没有做任何有用的事情

现在回答你的问题,是的,这种行为是预期的。想象一下,如果它更新了.prototype。由于.prototype在所有实例之间共享,因此所有实例都将看到更新。那肯定不是你想要的

当你这么做的时候:

var derived = new Derived();
derived.value = 1;
您创建了一个从派生的.prototype继承的新对象

当你这么做的时候:

var derived = new Derived();
derived.value = 1;
您直接为该新对象指定了一个值

在分配之前,继承链是这样的:

  derived            Derived.prototype      Base.prototype       Object.prototype
+-----------+         +-----------+         +-----------+         +-----------+
|           |         |           |         |           |         |           |
|           |---------|  value:0  |---------|           |---------|           |
|           |         |           |         |           |         |           |
+-----------+         +-----------+         +-----------+         +-----------+
  derived            Derived.prototype      Base.prototype       Object.prototype
+-----------+         +-----------+         +-----------+         +-----------+
|           |         |           |         |           |         |           |
|  value:1  |---------|  value:0  |---------|           |---------|           |
|           |         |           |         |           |         |           |
+-----------+         +-----------+         +-----------+         +-----------+
作业结束后,看起来是这样的:

  derived            Derived.prototype      Base.prototype       Object.prototype
+-----------+         +-----------+         +-----------+         +-----------+
|           |         |           |         |           |         |           |
|           |---------|  value:0  |---------|           |---------|           |
|           |         |           |         |           |         |           |
+-----------+         +-----------+         +-----------+         +-----------+
  derived            Derived.prototype      Base.prototype       Object.prototype
+-----------+         +-----------+         +-----------+         +-----------+
|           |         |           |         |           |         |           |
|  value:1  |---------|  value:0  |---------|           |---------|           |
|           |         |           |         |           |         |           |
+-----------+         +-----------+         +-----------+         +-----------+
所以在赋值之前,如果在派生对象上查找值,它将找不到,所以它将跳转到derived.prototype,在那里它将找到它

但是赋值之后,该值将直接在派生对象上找到

使用第二种方法,原型链将开始如下所示:

  derived            Derived.prototype      Base.prototype       Object.prototype
+-----------+         +-----------+         +-----------+         +-----------+
|           |         |           |         |           |         |           |
|           |---------|           |---------|  value:0  |---------|           |
|           |         |           |         |           |         |           |
+-----------+         +-----------+         +-----------+         +-----------+
因此,当在派生上查找值时,它将在找到value属性之前从派生到派生的.prototype再到Base.prototype进行遍历

假设您从派生构造函数创建了一组对象。上面的草图将更改,以便您创建的每个对象都指向派生的.prototype

现在,您可能会明白为什么不想更新原型了


如果我们使用了派生的\u 1.value=42,并且它更新了派生的.prototype对象,那么当您从派生的\u 2和派生的\u 3中查找值时,您将得到分配给派生的\u 1的值。

首先,在不在主题中时,删除这一行:

Base.prototype.constructor = Base;
它没有做任何有用的事情

现在回答你的问题,是的,这种行为是预期的。想象一下,如果它更新了.prototype。由于.prototype在所有实例之间共享,因此所有实例都将看到更新。那肯定不是你想要的

当你这么做的时候:

var derived = new Derived();
derived.value = 1;
您创建了一个从派生的.prototype继承的新对象

当你这么做的时候:

var derived = new Derived();
derived.value = 1;
您直接为该新对象指定了一个值

在分配之前,继承链是这样的:

  derived            Derived.prototype      Base.prototype       Object.prototype
+-----------+         +-----------+         +-----------+         +-----------+
|           |         |           |         |           |         |           |
|           |---------|  value:0  |---------|           |---------|           |
|           |         |           |         |           |         |           |
+-----------+         +-----------+         +-----------+         +-----------+
  derived            Derived.prototype      Base.prototype       Object.prototype
+-----------+         +-----------+         +-----------+         +-----------+
|           |         |           |         |           |         |           |
|  value:1  |---------|  value:0  |---------|           |---------|           |
|           |         |           |         |           |         |           |
+-----------+         +-----------+         +-----------+         +-----------+
作业结束后,看起来是这样的:

  derived            Derived.prototype      Base.prototype       Object.prototype
+-----------+         +-----------+         +-----------+         +-----------+
|           |         |           |         |           |         |           |
|           |---------|  value:0  |---------|           |---------|           |
|           |         |           |         |           |         |           |
+-----------+         +-----------+         +-----------+         +-----------+
  derived            Derived.prototype      Base.prototype       Object.prototype
+-----------+         +-----------+         +-----------+         +-----------+
|           |         |           |         |           |         |           |
|  value:1  |---------|  value:0  |---------|           |---------|           |
|           |         |           |         |           |         |           |
+-----------+         +-----------+         +-----------+         +-----------+
所以在赋值之前,如果在派生对象上查找值,它将找不到,所以它将跳转到derived.prototype,在那里它将找到它

但是赋值之后,该值将直接在派生对象上找到

使用第二种方法,原型链将开始如下所示:

  derived            Derived.prototype      Base.prototype       Object.prototype
+-----------+         +-----------+         +-----------+         +-----------+
|           |         |           |         |           |         |           |
|           |---------|           |---------|  value:0  |---------|           |
|           |         |           |         |           |         |           |
+-----------+         +-----------+         +-----------+         +-----------+
因此,当在派生上查找值时,它将在找到value属性之前从派生到派生的.prototype再到Base.prototype进行遍历

假设您从派生构造函数创建了一组对象。上面的草图将更改,以便您创建的每个对象都指向派生的.prototype

现在,您可能会明白为什么不想更新原型了

如果我们使用了派生的_1.value=42,并且它更新了派生的.prototype对象,那么当您从派生的_2和派生的_3中查找值时,您将得到分配给派生的_1的值

值已作为新属性添加。这不应该改变原型中的值吗

不,这种行为是意料之中的。属性仅在获取时继承,而不是在设置时继承。将值指定给object1的属性后,将更改或创建该对象上的属性

1:除了有一个

或者我是否明确需要通过原型(例如,deri)访问该值 ved.value.prototype.value=5

要更改原型上的值,您需要在原型上指定它,是的。对你来说,那就是

Derived.prototype.value = 5;

顺便说一句,请注意,在派生的.prototype上根本不应该存在在基构造函数中为每个实例创建的属性-请参阅。而不是派生。原型=新基础;你应该使用

Derived.prototype = Object.create(Base.prototype);
值已作为新属性添加。这不应该改变原型中的值吗

不,这种行为是意料之中的。属性仅在获取时继承,而不是在设置时继承。将值指定给object1的属性后,将更改或创建该对象上的属性

1:除了有一个

或者我是否明确需要通过原型访问该值-例如,派生的.value.prototype.value=5

要更改原型上的值,您需要在原型上指定它,是的。对你来说,那就是

Derived.prototype.value = 5;

顺便说一句,请注意,在派生的.prototype上根本不应该存在在基构造函数中为每个实例创建的属性-请参阅。而不是派生。原型=新基础;你应该使用

Derived.prototype = Object.create(Base.prototype);


是的,这是预期的。最好不要创建父实例来设置子实例的原型。而是使用Object.create继承和mix-ins在这里进行了详细解释:是的,这是预期的。最好不要创建父对象的实例来设置子对象的原型。而是使用Object.create继承和mix-ins在这里有详细的解释:嘿!非常感谢您的精彩回复。我想我现在对引擎盖下实际发生的事情有了更好的理解,但我不知道如何“正确”使用继承。在这两种情况下,虽然做了预期的事情,但他们并没有做我真正想要的事情。在第一种情况下,我将如何修改原型上的属性,而不是创建新的值属性?@Tom:您将以与当前相同的方式修改原型。。。通过执行Derived.prototype.foo=bar;。请记住,除非每个对象都有自己的foo属性,否则它们都会看到相同的bar值。您要更新.prototype的唯一时间是在所有实例之间共享数据。最常见的例子是提供所有对象的方法。如果我理解正确,你会用原型存储一个变量,以类似的方式让一个成员在C或C++中的类上静态吗?@汤姆:如果一个静态成员是从所有实例中观察到的值,那么答案就是这样。问题在于,对于数字和字符串等基本数据,您的实例必须专门修改其构造函数的.prototype。如果一个不小心声明了自己的属性,那么它将无法再获得.prototype。对于这些类型的静态变量,将其放在构造函数本身上可能更常见。派生值=42。现在,必须通过构造函数而不是此函数来访问该值。很酷,谢谢,我已经更新了我的问题,并获得了我想要的行为,现在对JS的理解也更好了!:谢谢你的帮助!嘿!非常感谢您的精彩回复。我想我现在对引擎盖下实际发生的事情有了更好的理解,但我不知道如何“正确”使用继承。在这两种情况下,虽然做了预期的事情,但他们并没有做我真正想要的事情。在第一种情况下,我将如何修改原型上的属性,而不是创建新的值属性?@Tom:您将以与当前相同的方式修改原型。。。通过执行Derived.prototype.foo=bar;。请记住,除非每个对象都有自己的foo属性,否则它们都会看到相同的bar值。您要更新.prototype的唯一时间是在所有实例之间共享数据。最常见的例子是提供所有对象的方法。如果我理解正确,你会用原型存储一个变量,以类似的方式让一个成员在C或C++中的类上静态吗?@汤姆:如果一个静态成员是从所有实例中观察到的值,那么答案就是这样。问题在于,对于数字和字符串等基本数据,您的实例必须专门修改其构造函数的.prototype。如果一个不小心声明了自己的属性,那么它将无法再获得.prototype。对于这些类型的静态变量,将其放在构造函数本身上可能更常见。派生值=42。现在,必须通过构造函数而不是此函数来访问该值。很酷,谢谢,我已经更新了我的问题,并获得了我想要的行为,现在对JS的理解也更好了!:谢谢你的帮助!感谢您提供了非常有用的答案,我将使用Object.create.重复我的测试用例。。看看这是否会产生我想要的行为。您关于使用Object.create的提示。。在钱上,我更新了我的问题,我的问题解决了,谢谢!Th
如果您能给出一个非常有用的答案,我将使用Object.create.重复我的测试用例。。看看这是否会产生我想要的行为。您关于使用Object.create的提示。。在钱上,我更新了我的问题,我的问题解决了,谢谢!