这张图再次表明,每个对象都有一个原型。构造函数 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操作符创建一个对象, 这些函数中的任何一个都可以是构造函数。

其他回答

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

 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”。

我试试四年级的解释:

事情很简单。原型是如何构建某样东西的例子。所以:

我是一个函数,我构建与原型相似的新对象 我是一个对象,我是用我的__proto__作为例子来构建的

证明:

function Foo() { }

var bar = new Foo()

// `bar` is constructed from how Foo knows to construct objects
bar.__proto__ === Foo.prototype // => true

// bar is an instance - it does not know how to create objects
bar.prototype // => undefined

[[原型]]:

[[Prototype]]是JS中对象的内部隐藏属性,它是对另一个对象的引用。每个对象在创建时都会接收一个非空值[[Prototype]]。请记住,当我们引用对象上的属性(如myObject.a)时调用[[Get]]操作。如果对象本身有一个属性,那么该属性将被使用。

let myObject= {
    a: 2
};

console.log(myObject.a);            // 2

但是如果对象本身直接没有所请求的属性,那么[[Get]]操作将继续遵循对象的[[Prototype]]链接。这个过程将继续进行,直到找到匹配的属性名或[[Prototype]]链结束(在内置的Object.prototype处)。如果没有找到匹配的属性,则返回undefined。object. create(specifiedObject)创建一个带有[[Prototype]]链接到指定对象的对象。

let anotherObject= {
    a: 2
};

// create an object linked to anotherObject
let myObject= Object.create(anotherObject);
console.log(myObject.a);                // 2

Both for..in loop and in operator use [[Prototype]] chain lookup process. So if we use for..in loop to iterate over the properties of an object then all the enumerable properties which can be reached via that object's [[Prototype]] chain also will be enumerated along with the enumerable properties of the object itself. And when using in operator to test for the existence of a property on an object then in operator will check all the properties via [[Prototype]] linkage of the object regardless of their enumerability.

// for..in loop uses [[Prototype]] chain lookup process
let anotherObject= {
    a: 2
};

let myObject= Object.create(anotherObject);

for(let k in myObject) {
    console.log("found: " + k);            // found: a
}

// in operator uses [[Prototype]] chain lookup process
console.log("a" in myObject);              // true

.prototype:

.prototype是JS中函数的一个属性,它引用了一个具有构造函数属性的对象,该对象存储了函数对象的所有属性(和方法)。

let foo= function(){}

console.log(foo.prototype);        
// returns {constructor: f} object which now contains all the default properties

foo.id= "Walter White";

foo.job= "teacher";

console.log(foo.prototype);       
// returns {constructor: f} object which now contains all the default properties and 2 more properties that we added to the fn object
/*
{constructor: f}
    constructor: f()
        id: "Walter White"
        job: "teacher"
        arguments: null
        caller: null
        length: 0
        name: "foo"
        prototype: {constructor: f}
        __proto__: f()
        [[FunctionLocation]]: VM789:1
        [[Scopes]]: Scopes[2]
    __proto__: Object

*/

但是JS中的普通对象没有.prototype属性。我们知道客体。prototype是JS中所有对象的根对象。所以很明显Object是一个函数,即typeof Object === "function"。这意味着我们还可以从object函数创建对象,比如let myObj= new object()。类似地,Array, Function也是函数,所以我们可以使用Array。原型,函数。用于存储数组和函数的所有通用属性的原型。所以我们可以说JS是建立在函数之上的。

{}.prototype;                            // SyntaxError: Unexpected token '.'

(function(){}).prototype;                // {constructor: f}

Also using new operator if we create objects from a function then internal hidden [[Prototype]] property of those newly created objects will point to the object referenced by the .prototype property of the original function. In the below code, we have created an object, a from a fn, Letter and added 2 properties one to the fn object and another to the prototype object of the fn. Now if we try to access both of the properties on the newly created object, a then we only will be able to access the property added to the prototype object of the function. This is because the prototype object of the function is now on the [[Prototype]] chain of the newly created object, a.

let Letter= function(){}

let a= new Letter();

Letter.from= "Albuquerque";

Letter.prototype.to= "New Hampshire";

console.log(a.from);                // undefined

console.log(a.to);                  // New Hampshire

.__proto__:

.__proto__是JS中对象的属性,它引用[[Prototype]]链中的另一个对象。我们知道[[Prototype]]是JS中对象的内部隐藏属性,它引用了[[Prototype]]链中的另一个对象。我们可以通过两种方式获取或设置内部[[Prototype]]属性引用的对象

Object.getPrototypeOf(obj) / Object.setPrototypeOf(obj) obj.__proto__

我们可以使用.__proto__.__proto__遍历[[Prototype]]链。与.constructor, . tostring (), . isprototypeof()一起,我们的dunder prototo属性(__proto__)实际上存在于内置对象中。原型根对象,但可用于任何特定对象。我们的.__proto__实际上是一个getter/setter。Object中.__proto__的实现。原型如下:

Object.defineProperty(Object.prototype, "__proto__", {
    get: function() {
        return Object.getPrototypeOf(this);
    },
    set: function(o) {
        Object.setPrototypeOf(this, o);
        return o;
    }
});

检索obj的值。__proto__类似于调用,obj.__proto__(),它实际上返回了getter fn, Object. getprototypeof (obj),它存在于Object上。原型对象。虽然.__proto__是一个可设置的属性,但由于性能问题,我们不应该更改已经存在的对象的[[Prototype]]。

如果使用new操作符从函数创建对象,那么这些新创建对象的内部隐藏[[Prototype]]属性将指向原始函数的. Prototype属性引用的对象。使用.__proto__属性,我们可以访问由对象的内部隐藏[[Prototype]]属性引用的另一个对象。但是__proto__并不等同于[[Prototype]],而是它的getter/setter。考虑下面的代码:

let Letter= function() {}

let a= new Letter();

let b= new Letter();

let z= new Letter();

// output in console
a.__proto__ === Letter.prototype;               // true

b.__proto__ === Letter.prototype;               // true

z.__proto__ === Letter.prototype;               // true

Letter.__proto__ === Function.prototype;        // true

Function.prototype.__proto__ === Object.prototype;        // true

Letter.prototype.__proto__ === Object.prototype;          // true

这个问题有很多很好的答案,但为了概括和紧凑形式的答案,我添加了以下内容:

我们必须考虑的第一件事是,当JS发明的时候,计算机的内存非常低,所以如果我们需要一个进程来创建新的对象类型,我们必须考虑内存性能。

因此,他们在内存的独立部分,定位由特定对象类型创建的对象需要的方法,而不是每次我们创建一个新对象时,在对象之外存储方法。 因此,如果我们用JS的新特性重新定义新的运算符和构造函数概念,我们有以下步骤:

和空对象。(这将是对象类型实例化的最终结果)

let empty={}

我们已经知道,由于内存性能原因,对象类型实例所需的所有方法都位于构造函数的prototype属性上。(函数也是对象,所以它们可以有属性) 因此,我们将空对象的__protp__引用到这些方法存在的位置。 (我们将概念上作为构造函数使用的函数命名为构造函数。

empty.__proto__ = constructor.prototype

我们必须初始化对象类型值。 在JS中的函数与对象断开连接。使用点表示法或函数对象的bind call apply等方法,我们必须知道“函数的上下文是什么”。

let newFunc = constructor.bind(empty)

现在我们有了一个新函数,它有一个空对象作为这个context。 执行此函数后。空对象将被填充,如果定义的构造函数函数没有返回,类型object的实例化结果将是这个空对象(就好像这将是该过程的结果一样)

所以正如你所看到的,__proto__是一个对象的属性,它引用了其他对象(在JS中函数也是对象)原型对象属性,它由跨特定对象类型的实例使用的属性组成。

正如你可以从短语中猜到的那样,函数是对象,函数也有__proto__属性,因此它们可以引用其他对象的prototype属性。这就是原型继承的实现方式。

(函数(){ 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) }) ()

试着理解这段代码