这张图再次表明,每个对象都有一个原型。构造函数
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年)。
我为自己画了一个小图,代表以下代码片段:
var Cat = function() {}
var tom = new Cat()
我有经典的OO背景,所以用这种方式表示层次结构很有帮助。为了帮助您阅读此图表,请将图像中的矩形视为JavaScript对象。是的,函数也是对象。;)
JavaScript中的对象有属性,__proto__只是其中之一。
此属性背后的思想是指向(继承)层次结构中的祖先对象。
JavaScript的根对象是object。Prototype和所有其他对象都是这个对象的后代。根对象的__proto__属性为null,表示继承链的结束。
你会注意到原型是函数的属性。Cat是一个函数,但function和Object也是(本机)函数。Tom不是一个函数,因此它没有这个属性。
此属性背后的思想是指向一个将在构造中使用的对象,即当您在该函数上调用new操作符时。
注意,原型对象(黄色矩形)有另一个属性称为
构造函数,它指向各自的函数对象。为
简短的原因,这是没有描述。
实际上,当我们用new Cat()创建tom对象时,所创建的对象的__proto__属性将被设置为构造函数的原型对象。
最后,让我们稍微研究一下这个图表。以下陈述是正确的:
汤姆。__proto__属性指向与Cat.prototype相同的对象。
猫。__proto__指向函数。原型对象,就像函数一样。__proto__和Object。__proto__做。
Cat.prototype。__proto__和tom.__proto__。__proto__指向相同的对象,即object .prototype。
干杯!
只有一个对象用于原型链接。该对象显然有一个名称和值:__proto__是它的名称,prototype是它的值。这是所有。
为了让它更容易理解,看看这篇文章顶部的图表(由dmitry soshnikov绘制的图表),你永远不会发现__proto__的值指向prototype以外的其他东西。
要点是:__proto__是引用原型对象的名称,prototype是实际的原型对象。
这就像是在说:
let x = {name: 'john'};
X是对象名称(指针),{name: 'john'}是实际对象(数据值)。
注意:这只是一个非常简单的提示,说明它们在较高的水平上是如何相互关联的。
更新:下面是一个简单具体的javascript示例,以便更好地说明:
let x = new String("testing") // Or any other javascript object you want to create
Object.getPrototypeOf(x) === x.__proto__; // true
这意味着当Object.getPrototypeOf(x)为我们获取x的实际值(这是它的原型)时,正是x的__proto__所指向的。因此__proto__确实指向x的原型。因此__proto__引用x (x的指针),而prototype是x的值(它的原型)。
我希望现在大家都明白了。
对于任何想要了解原型继承的人来说,这都是一个非常重要的问题。根据我的理解,默认情况下,当从函数中使用new创建对象时,prototype会被赋值,因为function定义了prototype对象:
function protofoo(){
}
var protofoo1 = new protofoo();
console.log(protofoo.prototype.toString()); //[object Object]
当我们创建一个普通的对象,没有new,即显式地从一个函数,它没有原型,但它有一个空的原型,可以分配一个原型。
var foo={
check: 10
};
console.log(foo.__proto__); // empty
console.log(bar.prototype); // TypeError
foo.__proto__ = protofoo1; // assigned
console.log(foo.__proto__); //protofoo
我们可以使用Object。创建以显式链接对象。
// we can create `bar` and link it to `foo`
var bar = Object.create( foo );
bar.fooprops= "We checking prototypes";
console.log(bar.__proto__); // "foo"
console.log(bar.fooprops); // "We checking prototypes"
console.log(bar.check); // 10 is delegated to `foo`
在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.
让我用一个简单的例子来解释:
function User(email, name){
this.email = email;
this.name = name;
this.online = false;
// method directly added to the constructor
this.greet = ()=>{
console.log(`Hi ${this.name}`);
}
}
// Adding prototype method login to the constructor function.
User.prototype.login = function(){
this.online = true;
console.log(this.email, 'has logged in');
};
// Adding prototype method logout to the constructor function.
User.prototype.logout = function(){
this.online = false;
console.log(this.email, 'has logged out');
};
var userOne = new User('ryu@ninjas.com', 'Ryu');
var userTwo = new User('yoshi@mariokorp.com', 'Yoshi');
console.log(userOne);
userTwo.login();
userTwo.greet();
输出:
结论:
在构造函数中添加的属性和方法是
直接添加到对象中。
添加的属性和方法
.prototype。被添加到对象的__proto__属性中。我们甚至可以看到userOne。__proto__或userTwo.__proto__