这张图再次表明,每个对象都有一个原型。构造函数
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 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”。
我为自己画了一个小图,代表以下代码片段:
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。
干杯!
在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 Dog(){}
Dog.prototype.bark = "woof"
let myPuppie = new Dog()
现在,myPupppie有__proto__属性指向Dog.prototype。
> myPuppie.__proto__
>> {bark: "woof", constructor: ƒ}
但是mypuppy没有原型属性。
> myPuppie.prototype
>> undefined
因此,mypuppie的__proto__是对用于实例化此对象的构造函数的.prototype属性的引用(当前mypuppie对象与此__proto__对象具有“委托”关系),而mypuppie的.prototype属性则根本不存在(因为我们没有设置它)。
MPJ的解释很好:
在JavaScript中创建对象