这张图再次表明,每个对象都有一个原型。构造函数 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年)。


当前回答

'use strict'
function A() {}
var a = new A();
class B extends A {}
var b = new B();
console.log('====='); // =====
console.log(B.__proto__ === A); // true
console.log(B.prototype.__proto__ === A.prototype); // true
console.log(b.__proto__ === B.prototype); // true
console.log(a.__proto__ === A.prototype); // true
console.log(A.__proto__ === Function.__proto__); // true
console.log(Object.__proto__ === Function.__proto__); // true
console.log(Object.prototype === Function.__proto__.__proto__); // true
console.log(Object.prototype.__proto__ === null); // true

在JavaScript中,每个对象(函数也是对象!)都有__proto__属性,该属性是对其原型的引用。

当我们使用new操作符和构造函数一起创建一个新对象时, 新对象的__proto__属性将被设置为构造函数的prototype属性, 然后构造函数将由new对象调用, 在这个过程中,“this”将是构造函数作用域中对新对象的引用,最终返回新对象。

构造函数的prototype是__proto__属性,构造函数的prototype属性是work with new操作符。

构造函数必须是函数,但函数并不总是构造函数,即使它具有prototype属性。

Prototype chain实际上是对象的__proto__属性,用于引用其原型, 以及原型的__proto__属性来引用原型的原型,等等, 直到引用Object的原型的__proto__属性,该属性引用为null。

例如:

console.log(a.constructor === A); // true
// "a" don't have constructor,
// so it reference to A.prototype by its ``__proto__`` property,
// and found constructor is reference to A

[[Prototype]]和__proto__属性实际上是一样的。

我们可以使用Object的getPrototypeOf方法来获取某个对象的原型。

console.log(Object.getPrototypeOf(a) === a.__proto__); // true

我们编写的任何函数都可以用new操作符创建一个对象, 这些函数中的任何一个都可以是构造函数。

其他回答

(函数(){ Let a = function(){console.log(this.b)}; A.prototype.b = 1; a.__proto__。B = 2; 设q = new a(); console.log (a.b); console.log (q.b) }) ()

试着理解这段代码

我知道,我迟到了,但让我试着简化一下。

假设有一个函数

    function Foo(message){

         this.message = message ; 
     };

     console.log(Foo.prototype);

Foo函数将有一个原型对象链接。所以,无论何时我们在JavaScript中创建一个函数,它总是有一个原型对象链接到它。

现在让我们继续使用函数Foo创建两个对象。

    var a = new Foo("a");
    var b = new Foo("b");
    console.log(a.message);
    console.log(b.message);

现在我们有两个对象,对象a和对象b。它们都被创建了 使用构造函数Foo。记住,构造函数在这里只是一个词。 对象a和b都有message属性的副本。 这两个对象a和b链接到构造函数Foo的原型对象。 在对象a和b上,我们可以在所有浏览器中使用__proto__属性访问Foo prototype,在IE中我们可以使用Object.getPrototypeOf(a)或Object.getPrototypeOf(b)

现在,Foo。Prototype, a.__proto__和b.__proto__都表示同一个对象。

    b.__proto__ === Object.getPrototypeOf(a);
    a.__proto__ ===  Foo.prototype;
    a.constructor.prototype  === a.__proto__;

所有这些都将返回true。

如我们所知,在JavaScript中属性可以动态添加。我们可以向对象添加属性

    Foo.prototype.Greet = function(){

         console.log(this.message);
    }
    a.Greet();//a
    b.Greet();//b
    a.constructor.prototype.Greet();//undefined 

如你所见,我们在Foo中添加了Greet()方法。但它可以在a和b或任何其他使用Foo构造的对象中访问。

在执行a.Greet()时,JavaScript将首先在对象a的属性列表中搜索Greet。如果没有找到,它将在a. Since a.__proto__和Foo的__proto__链中上升。prototype是同一个对象,JavaScript会找到Greet()方法并执行它。

我希望,现在prototype和__proto__被简化了一点。

对于静态方法使用__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

一种很好的思考方式是……

Prototype用于构造函数。它真的应该被称为“prototypeToInstall”,因为它就是这样的。

__proto__是对象上的“已安装原型”(由上述构造函数()函数创建/安装在对象上)

__proto__是在类/函数的实例创建时创建的。基本上,它包含创建实例的类/函数的原型。 原型包含可以被链接的实际原型。