这张图再次表明,每个对象都有一个原型。构造函数
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年)。
简介:
对象的__proto__属性是映射到该对象的构造函数原型的属性。换句话说:
实例。__proto__ ===构造函数。原型// true
这用于形成对象的原型链。原型链是一个对象属性的查找机制。如果访问对象的属性,JavaScript将首先查看对象本身。如果属性在那里没有找到,它将一路攀升到原链,直到它被找到(或没有)
例子:
人(姓名、城市){
This.name = name;
}
Person.prototype.age = 25;
const willem =新人(' willem ');
console.log(威廉。__proto__ === Person.prototype);//实例上的__proto__属性指向构造函数的原型
console.log (willem.age);// 25没有在willem object中找到它,但在prototype中存在
console.log (willem.__proto__.age);//现在我们直接访问Person函数的原型
第一个日志的结果为true,这是因为构造函数创建的实例的__proto__属性引用了构造函数的prototype属性。记住,在JavaScript中,函数也是对象。对象可以有属性,任何函数的默认属性都是一个名为prototype的属性。
然后,当这个函数被用作构造函数时,从它实例化的对象将接收一个名为__proto__的属性。这个__proto__属性引用了构造函数的prototype属性(默认情况下每个函数都有)。
为什么这个有用?
JavaScript在查找对象属性时有一种叫做“原型继承”的机制,下面是它的基本功能:
First, it's checked if the property is located on the Object itself. If so, this property is returned.
If the property is not located on the object itself, it will 'climb up the protochain'. It basically looks at the object referred to by the __proto__ property. There, it checks if the property is available on the object referred to by __proto__.
If the property isn't located on the __proto__ object, it will climb up the __proto__ chain, all the way up to Object object.
If it cannot find the property anywhere on the object and its prototype chain, it will return undefined.
例如:
人(名){
This.name = name;
}
let mySelf =新人(“威廉”);
console.log(我自己。__proto__ === Person.prototype);
console.log (mySelf.__proto__。__proto__ === Object.prototype);
在JavaScript中,函数可以用作构造函数。这意味着我们可以使用new关键字从它们中创建对象。每个构造函数都带有一个内置对象。这个内置对象称为原型。构造函数的实例使用__proto__来访问其构造函数的prototype属性。
First we created a constructor: function Foo(){}. To be clear, Foo is just another function. But we can create an object from it with the new keyword. That's why we call it the constructor function
Every function has a unique property which is called the prototype property. So, Constructor function Foo has a prototype property which points to its prototype, which is Foo.prototype (see image).
Constructor functions are themselves a function which is an instance of a system constructor called the [[Function]] constructor. So we can say that function Foo is constructed by a [[Function]] constructor. So, __proto__ of our Foo function will point to the prototype of its constructor, which is Function.prototype.
Function.prototype is itself is nothing but an object which is constructed from another system constructor called [[Object]]. So, [[Object]] is the constructor of Function.prototype. So, we can say Function.prototype is an instance of [[Object]]. So __proto__ of Function.prototype points to Object.prototype.
Object.prototype is the last man standing in the prototype chain. I mean it has not been constructed. It's already there in the system. So its __proto__ points to null.
Now we come to instances of Foo. When we create an instance using new Foo(), it creates a new object which is an instance of Foo. That means Foo is the constructor of these instances. Here we created two instances (x and y). __proto__ of x and y thus points to Foo.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]]以及它是如何工作的。