这张图再次表明,每个对象都有一个原型。构造函数
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年)。
这个问题有很多很好的答案,但为了概括和紧凑形式的答案,我添加了以下内容:
我们必须考虑的第一件事是,当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属性。这就是原型继承的实现方式。
定义
(括号()内的数字是一个“链接”到下面写的代码)
原型-一个对象,包括:
=>函数(3)
prototype(5)
通过此构造函数(1)创建或将创建的对象(4)
=>构造函数本身(1)
=>此特定对象的__proto__ (prototype对象)
__proto__ (dandor prototype ?) -通过特定构造函数(1)创建的任何对象(2)和该构造函数的原型对象的属性(5)之间的链接,允许每个创建的对象(2)访问原型的函数和方法(4)(__proto__默认包含在JS中的每个对象中)
代码说明
1.
function Person (name, age) {
this.name = name;
this.age = age;
}
2.
var John = new Person(‘John’, 37);
// John is an object
3.
Person.prototype.getOlder = function() {
this.age++;
}
// getOlder is a key that has a value of the function
4.
John.getOlder();
5.
Person.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属性。这就是原型继承的实现方式。
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]]以及它是如何工作的。