这张图再次表明,每个对象都有一个原型。构造函数 function Foo也有自己的__proto__,也就是function .prototype, 而它又通过__proto__属性再次引用 Object.prototype。因此,重复,Foo。原型只是一个显式 Foo的属性,引用b和c对象的原型。

var b = new Foo(20);
var c = new Foo(30);

__proto__和prototype之间有什么区别?

这一数据来自dmitrysoshnikov.com网站。

注:上述2010年的文章现在有第二版(2017年)。


当前回答

Prototype VS. __proto__ VS. [[Prototype]]

在创建函数时,会自动创建一个名为prototype的属性对象(不是您自己创建的),并将其附加到函数对象(构造函数)。注意:这个新的原型对象也指向本机JavaScript对象,或者有一个内部私有链接。

例子:

function Foo () {
    this.name = 'John Doe';
}

// Foo has an object property called prototype.
// prototype was created automatically when we declared the function Foo.
Foo.hasOwnProperty('prototype'); // true

// Now, we can assign properties and methods to it:
Foo.prototype.myName = function () {
    return 'My name is ' + this.name;
}

如果你使用new关键字从Foo中创建一个新对象,你基本上是在创建一个新对象,它有一个内部或私有的链接到我们之前讨论过的函数Foo的原型:

var b = new Foo();

b.[[Prototype]] === Foo.prototype  // true

到该函数对象的私有链接称为双括号prototype或[[prototype]]。许多浏览器为我们提供了一个公共链接,称为__proto__!

更具体地说,__proto__实际上是一个属于原生JavaScript对象的getter函数。它返回this绑定的内部私有原型链接(返回b的[[prototype]]):

b.__proto__ === Foo.prototype // true

值得注意的是,ECMAScript5的启动,你也可以使用getPrototypeOf方法来获得内部的私有链接:

Object.getPrototypeOf(b) === b.__proto__ // true

注意:这个答案并不打算涵盖创建新对象或新构造函数的整个过程,而是帮助更好地理解__proto__、prototype和[[prototype]]以及它是如何工作的。

其他回答

Prototype VS. __proto__ VS. [[Prototype]]

在创建函数时,会自动创建一个名为prototype的属性对象(不是您自己创建的),并将其附加到函数对象(构造函数)。注意:这个新的原型对象也指向本机JavaScript对象,或者有一个内部私有链接。

例子:

function Foo () {
    this.name = 'John Doe';
}

// Foo has an object property called prototype.
// prototype was created automatically when we declared the function Foo.
Foo.hasOwnProperty('prototype'); // true

// Now, we can assign properties and methods to it:
Foo.prototype.myName = function () {
    return 'My name is ' + this.name;
}

如果你使用new关键字从Foo中创建一个新对象,你基本上是在创建一个新对象,它有一个内部或私有的链接到我们之前讨论过的函数Foo的原型:

var b = new Foo();

b.[[Prototype]] === Foo.prototype  // true

到该函数对象的私有链接称为双括号prototype或[[prototype]]。许多浏览器为我们提供了一个公共链接,称为__proto__!

更具体地说,__proto__实际上是一个属于原生JavaScript对象的getter函数。它返回this绑定的内部私有原型链接(返回b的[[prototype]]):

b.__proto__ === Foo.prototype // true

值得注意的是,ECMAScript5的启动,你也可以使用getPrototypeOf方法来获得内部的私有链接:

Object.getPrototypeOf(b) === b.__proto__ // true

注意:这个答案并不打算涵盖创建新对象或新构造函数的整个过程,而是帮助更好地理解__proto__、prototype和[[prototype]]以及它是如何工作的。

对于静态方法使用__proto__怎么样?

function Foo(name){
  this.name = name
  Foo.__proto__.collection.push(this)
  Foo.__proto__.count++

}

Foo.__proto__.count=0
Foo.__proto__.collection=[]

var bar = new Foo('bar')
var baz = new Foo('baz')

Foo.count;//2
Foo.collection // [{...}, {...}]
bar.count // undefined

为了解释,让我们创建一个函数

 function a (name) {
  this.name = name;
 }

当JavaScript执行这段代码时,它将prototype属性添加到。prototype属性是一个具有两个属性的对象:

构造函数 __proto__

所以当我们这样做的时候

a.原型它返回

     constructor: a  // function definition
    __proto__: Object

现在你可以看到构造函数就是函数a本身 而__proto__指向JavaScript的根对象。

让我们看看当我们使用带有new关键字的函数时会发生什么。

var b = new a ('JavaScript');

当JavaScript执行这段代码时,它会做4件事:

它创建了一个新对象,一个空对象// {} 它在b上创建__proto__,并使其指向a.prototype,因此b.__proto__ === a.prototype 它使用新创建的对象(在步骤#1中创建)作为上下文(this)执行a.p otype.constructor(这是函数a的定义),因此作为'JavaScript'传递的name属性(它被添加到this)被添加到新创建的对象。 它返回新创建的对象(在步骤#1中创建),因此var b被分配给新创建的对象。

现在如果我们添加a.prototype。car = "BMW"然后 b.car,输出“BMW”出现。

这是因为当JavaScript执行这段代码时,它在b上搜索car属性,它没有发现,然后JavaScript使用b.__proto__(在步骤#2中指向“a.prototype”)并找到car属性,因此返回“BMW”。

另一种理解它的好方法是:

var foo = {}

/* 
foo.constructor is Object, so foo.constructor.prototype is actually 
Object.prototype; Object.prototype in return is what foo.__proto__ links to. 
*/
console.log(foo.constructor.prototype === foo.__proto__);
// this proves what the above comment proclaims: Both statements evaluate to true.
console.log(foo.__proto__ === Object.prototype);
console.log(foo.constructor.prototype === Object.prototype);

仅当支持IE11 __proto__后。在那个版本之前,比如IE9,你可以使用构造函数来获取__proto__. dll。

我碰巧从You Don't Know JS: this & Object prototyping中学习原型,这是一本很好的书,可以理解设计的底层,澄清许多误解(这就是为什么我试图避免使用继承和instanceof之类的东西)。

但我和这里的人有同样的问题。有几个答案真的很有帮助,很有启发性。我也很乐意分享我的理解。


什么是原型?

JavaScript中的对象有一个内部属性,在规范中表示为[[Prototype]],它只是对另一个对象的引用。几乎所有对象在创建时都会被赋予这个属性的非空值。

如何获得一个对象的原型?

通过__proto__或Object.getPrototypeOf

var a = { name: "wendi" };
a.__proto__ === Object.prototype // true
Object.getPrototypeOf(a) === Object.prototype // true

function Foo() {};
var b = new Foo();
b.__proto__ === Foo.prototype
b.__proto__.__proto__ === Object.prototype

原型是什么?

原型是作为函数的特殊属性自动创建的对象,用于建立委托(继承)链,即原型链。

当我们创建一个函数a时,prototype会自动作为a上的一个特殊属性创建,并将上的函数代码保存为prototype上的构造函数。

function Foo() {};
Foo.prototype // Object {constructor: function}
Foo.prototype.constructor === Foo // true

我想把这个属性作为存储函数对象的属性(包括方法)的地方。这也是JS中的实用函数被定义为Array.prototype.forEach()、Function.prototype.bind()、Object.prototype.toString()的原因。

为什么要强调函数的性质?

{}.prototype // undefined;
(function(){}).prototype // Object {constructor: function}

// The example above shows object does not have the prototype property.
// But we have Object.prototype, which implies an interesting fact that
typeof Object === "function"
var obj = new Object();

Arary, Function, Objectare都是函数。我必须承认,这刷新了我对JS的印象。我知道函数是JS中的一等公民,但它似乎是建立在函数之上的。

__proto__和prototype有什么区别?

__proto__a引用作用于每个对象以引用其[[Prototype]]属性。

Prototype是作为函数的特殊属性自动创建的对象,用于存储函数对象的属性(包括方法)。

有了这两个,我们可以在脑海中绘制出原型链。如图所示:

function Foo() {}
var b = new Foo();

b.__proto__ === Foo.prototype // true
Foo.__proto__ === Function.prototype // true
Function.prototype.__proto__ === Object.prototype // true