这张图再次表明,每个对象都有一个原型。构造函数
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年)。
我知道,我迟到了,但让我试着简化一下。
假设有一个函数
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__被简化了一点。
在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.
简介:
对象的__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);
这个问题有很多很好的答案,但为了概括和紧凑形式的答案,我添加了以下内容:
我们必须考虑的第一件事是,当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属性。这就是原型继承的实现方式。