javascript - JavaScript 中的对象继承

标签 javascript inheritance prototype

我的问题是关于维护其父对象原型(prototype)链的子对象。

在 John Resig 的 Advanced Javascript 幻灯片 (http://ejohn.org/apps/learn/#76) 中,他写道,为了维护子对象的原型(prototype)链,您必须实例化一个新的父对象。

然而,通过一些快速测试,我注意到原型(prototype)链是通过将子对象原型(prototype)设置为等于父对象原型(prototype)来维护的。

如有任何澄清,我们将不胜感激!

原始代码

function Person(){}
Person.prototype.dance = function(){};

function Ninja(){}

// Achieve similar, but non-inheritable, results
Ninja.prototype = Person.prototype;
Ninja.prototype = { dance: Person.prototype.dance };

assert( (new Ninja()) instanceof Person, "Will fail with bad prototype chain." );

// Only this maintains the prototype chain
Ninja.prototype = new Person();

var ninja = new Ninja();
assert( ninja instanceof Ninja, "ninja receives functionality from the Ninja prototype" );
assert( ninja instanceof Person, "... and the Person prototype" );
assert( ninja instanceof Object, "... and the Object prototype" );

我的修改版

function Person(){}
Person.prototype.dance = function(){console.log("Dance")};

function Ninja(){}

// Achieve similar, but non-inheritable, results
Ninja.prototype = Person.prototype;

assert( (new Ninja()) instanceof Person, "Will fail with bad prototype chain." );

var ninja = new Ninja();
assert( ninja instanceof Ninja, "ninja receives functionality from the Ninja prototype" );
assert( ninja instanceof Person, "... and the Person prototype" );
assert( ninja instanceof Object, "... and the Object prototype" );
ninja.dance();

最佳答案

在 John Resig 提供的代码中,他首先将 Ninja.prototype 设置为 Person.prototype。然后他立即将其重置为 { dance: Person.prototype.dance }:

// Achieve similar, but non-inheritable, results
Ninja.prototype = Person.prototype;
Ninja.prototype = { dance: Person.prototype.dance };

结果是 Ninja 构造函数创建的任何对象都将直接继承自 { dance: Person.prototype.dance } 而不是 的实例Person.prototype.因此 (new Ninja) instanceof Person 将返回 false。在这种情况下,原型(prototype)链是:

        null
         ^
         |
         | [[prototype]]
         |
+------------------+
| Object.prototype |
+------------------+
         ^
         |
         | [[prototype]]
         |
+------------------+
|  Ninja.prototype |
+------------------+
         ^
         |
         | [[prototype]]
         |
+------------------+
|     new Ninja    |
+------------------+

在修改后的版本中,您删除了对 Ninja.prototype 的第二个赋值,有效地将 Ninja.prototype 设置为 Person.prototype。因此原型(prototype)链是:

         null
          ^
          |
          | [[prototype]]
          |
+-------------------+
|  Object.prototype |
+-------------------+
          ^
          |
          | [[prototype]]
          |
+-------------------+
| Ninja.prototype / |
| Person.prototype  |
+-------------------+
          ^
          |
          | [[prototype]]
          |
+-------------------+
|     new Ninja     |
+-------------------+

请注意,由于 Ninja.prototypePerson.prototype 相同,(new Ninja) intanceof Ninja(new Ninja) instanceof Person 将返回 true。这是因为 instanceof operator depends on the prototype of a constructor .

然而,在 JavaScript 中实现继承的正确方法是将 Ninja.prototype 设置为 Object.create(Person.prototype)(或以老派方式到 new Person),在这种情况下,原型(prototype)链将是:

        null
         ^
         |
         | [[prototype]]
         |
+------------------+
| Object.prototype |
+------------------+
         ^
         |
         | [[prototype]]
         |
+------------------+
| Person.prototype |
+------------------+
         ^
         |
         | [[prototype]]
         |
+------------------+
|  Ninja.prototype |
+------------------+
         ^
         |
         | [[prototype]]
         |
+------------------+
|     new Ninja    |
+------------------+

注意:永远记住,在 JavaScript 中,对象继承自其他对象。它们从不继承构造函数。如果您想了解 JavaScript 中真正的原型(prototype)继承,请阅读我在 why prototypal inhritance matters 上的博客文章.

关于javascript - JavaScript 中的对象继承,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17768386/

相关文章:

javascript - 如何检测浏览器中是否安装了小书签?

objective-c - swift 中的动态子类实例化

c# - 调用重写方法的祖父实现

java - Java中的逆变和继承有什么区别?

javascript - 无法获取未定义或空引用的属性

javascript - 在 Highcharts 中创建仅跨越一个条形的图带

javascript - 在全局变量中存储 getJSON 数据,但后来说它未定义

带有参数的 Javascript 警报

javascript - 如何将原型(prototype)模式引入javascript命名空间

javascript - Javascript 中基本原型(prototype)设计的问题