使用继承时,构造函数和原型对象之间有什么区别吗?

Joh*_*ren 6 javascript

请考虑以下JavaScript代码段:

function foo() {
  this.bar = function() { };
}

// or... (if we used an empty constructor function)

foo.prototype.bar = function() { };
Run Code Online (Sandbox Code Playgroud)

我这样做有什么不同:

function baz() {
}

baz.prototype = new foo();
Run Code Online (Sandbox Code Playgroud)

在这两种情况下baz最终都有一名成员,bar但有什么区别?为什么我会在不同的地方这样做?

Fel*_*ing 10

区别在于物业所在的原型链中的位置.

假设我们有f = new foo();b = new baz().然后我们有以下情况:

foo不使用原型的定义:

+-----------+     +---------------+
|     f     |     | foo.prototype |
| __proto__-+---->| constructor   |  
| bar       |     |               |
+-----------+     +---------------+
Run Code Online (Sandbox Code Playgroud)

bar是对象本身的属性(f.howOwnProperty('bar')返回true).

如果您将属性分配给原型,则情况为:

+-----------+     +---------------+
|     f     |     | foo.prototype |
| __proto__-+---->| constructor   |  
|           |     | bar           |
+-----------+     +---------------+
Run Code Online (Sandbox Code Playgroud)

f没有自己的属性bar,但该属性与所有其他实例共享foo.

类似于第二个片段,其结果是

+-----------+     +---------------+     +---------------+
|     b     |     | foo instance  |     | foo.prototype |
| __proto__-+---->| __proto__    -+---->| constructor   |  
|           |     | bar           |     |               |
+-----------+     +---------------+     +---------------+
Run Code Online (Sandbox Code Playgroud)

要么

+-----------+     +---------------+     +---------------+
|     b     |     | foo instance  |     | foo.prototype |
| __proto__-+---->| __proto__    -+---->| constructor   |  
|           |     |               |     | bar           |
+-----------+     +---------------+     +---------------+
Run Code Online (Sandbox Code Playgroud)

你为什么要这样做?

它主要是关于结构而不是浪费记忆.您可以在构造函数中向对象添加函数:

function Foo() {
    this.bar = function() {};
}
Run Code Online (Sandbox Code Playgroud)

但是这也意味着每个实例Foo有它自己的功能,那就是,f1.bar === f2.bar就是false,虽然两者的功能都在做同样的事情.

使用原型为您提供了一种清晰的方法来分隔所有实例和特定于实例的属性.

最后,它是"正义" 继承,它是软件开发中的一个概念(如聚合),可以在任何有意义的地方使用.你的第二个片段基本上意味着a baz -a foo,所以baz除了自己的属性之外,foo实例与实例(继承)具有相同的属性.