这张图再次表明,每个对象都有一个原型。构造函数
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__被简化了一点。
正如这句话所说
__proto__是用于查找链的实际对象
原型是用来构建的对象
当你用new创建一个对象时:
(新的Foo)。__proto__ === Foo.prototype;
(新的Foo)。原型=== undefined;
我们可以进一步注意到,使用函数构造函数创建的对象的__proto__属性指向相应构造函数的prototype属性所指向的内存位置。
如果我们改变构造函数的prototype的内存位置,派生对象的__proto__仍将继续指向原始地址空间。因此,要使公共属性沿着继承链向下可用,总是将属性附加到构造函数函数原型,而不是重新初始化它(这会改变它的内存地址)。
考虑下面的例子:
function Human(){
this.speed = 25;
}
var himansh = new Human();
Human.prototype.showSpeed = function(){
return this.speed;
}
himansh.__proto__ === Human.prototype; //true
himansh.showSpeed(); //25
//now re-initialzing the Human.prototype aka changing its memory location
Human.prototype = {lhs: 2, rhs:3}
//himansh.__proto__ will still continue to point towards the same original memory location.
himansh.__proto__ === Human.prototype; //false
himansh.showSpeed(); //25