javascript - 原型(prototype)是怎么回事

标签 javascript prototype

<分区>

所以我有以下内容:

function A () { this.a = 0; }
function B () { this.b = 0; }
function C () {}

C.prototype = new B();

var c1 = new C();
var c2 = new C();

c1.b = 10;

console.log(c1.b); // 10 
console.log(c2.b); // 0

http://jsfiddle.net/Mars6/2/

当我将 B.b 更改为一个对象时,它似乎为每个新的 C 存储相同的对象:

function A () { this.a = 0; }
function B () { this.b = new A(); }
function C () {}

C.prototype = new B();

var c1 = new C();
var c2 = new C();

c1.b.a = 10;

console.log(c1.b.a); // 10 
console.log(c2.b.a); // 10 - I want this to be 0

http://jsfiddle.net/Mars6/1/

任何人都可以解释发生了什么/问题是什么。

最佳答案

当你做的时候

C.prototype = new B();

您没有说“每当您需要原型(prototype)时,就做new B”。你说的是“将原型(prototype)分配给 new B()(这应该不会很奇怪)。你得到的是:

C.prototype.b.a === 0

无论何时你做 new C,你都不是在复制 C.prototype - 你只是链接到它,链接到相同的 B 对象:

C.prototype = new B()
   ^    ^
   |    |
  c1    c2

c1.b === c2.b; //true

您可能知道,对象可以随心所欲地改变。因此,当您执行 c1.b.a = 4 时,您将进入底层对象并随意使用它。

编辑:第一个示例之所以有效,是因为属性解析的工作方式。 b 属性不驻留在对象 c1c2 上。当你说“给我 c1.b”时,js 引擎会做这样的事情:

  1. c1 上是否有b 属性?不,没有。
  2. 让我们看一下c1 的原型(prototype)(实际原型(prototype),对象从中获取其方法和属性的对象 - 在本例中为C.prototype)
  3. 哦,是的,它有一个 b 属性。归还它。

在实际的 js 中,这是 ( spec ):

function GetProperty (name, obj) {
    while (obj !== null) {
        if (obj.hasOwnProperty(name)) {
            return obj[name];
        }
        obj = Object.getPrototypeOf(obj);
    }
    return undefined;
}

因此,在 b 是一个对象的情况下,您已经掌握了一个对象。更改它会像普通对象一样更改它(请注意,您不是直接分配给 c1.b - 稍后您会明白我的意思)。用箭头解释:

C.prototype.b = 0
   ^     ^
   |     |
  c1.b   c2.b

这很重要,所以我要再次强调:当您获得 c1.b 时,您将获得一个对象,该对象可以像任何其他对象一样进行操作。为它分配属性就像任何其他普通对象一样,并改变它......好吧,改变它。

现在,在前一种情况下 (c1.b = 10),您实际上是在分配一个属性。这意味着您正在 c1 对象本身上创建一个键/值对。因此,在第一步中,我们查看 c1 是否有属性 b - 它确实有。用更多的箭头解释:

      C.prototype.b = 0
            ^
            |
  c1.b=10  c2.b

改变后一个例子,我们可以观察到同样的效果:

//changing
c1.b.a = 10;
//to
c1.b = 4;

c2.b !== 4 && c2.b.a === 0; //true

回顾一下:

  • 在前面的示例中,您只需在 c1 对象上设置一个属性。
  • 在后一个示例中,您在 c1 的原型(prototype)上为一个对象设置了一个属性,该属性在所有其他 C 对象上发生了变化。

关于javascript - 原型(prototype)是怎么回事,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17018686/

相关文章:

javascript - scrollTo() 和 jquery scrollTop() 在 Chrome 中不起作用

javascript - .slideToggle() 在使用 Jquery 3.1.1 时不起作用

javascript - HTML5 网络音频 API : Filters is not working

javascript - 如何扩展已在使用的 React 组件?

javascript - 更改 JavaScript 原型(prototype)上的函数

javascript - 检测对象数组中是否存在属性值

javascript - 页面 JavaScript 调用 Firefox 扩展 JavaScript

javascript - 如何在jquery中比较两个格式为 "dd-mm-yyyy hh:mm"的日期

objective-c - 为什么不能在每行声明多个方法原型(prototype)?

javascript - 有没有更优雅的 "fake"类继承方式?