JS对象中的[[Prototype]]、__proto__、pr

2023-03-12  本文已影响0人  奋斗_登
1. 对象

ECMA-262将对象定义为一组属性的无序集合。对象的每个属性或者方法都有一个名称来标识,这个名称映射到一个值。可以把对象想象成一张散列表,其中的内容就是一组键/值对,值可以是数据或者函数。

2. [[Prototype]] 是什么

ECMA-262使用一些内部特性来描述属性的特征。这些特性是由为JavaScript实现引擎的规范定义的。因此,开发者不能在JavaScript中直接访问这些特性。
为了将某个特性标识为内部特性,规范会用两个中括号把特性的名称括起来,比如[[Prototype]]、[[Enumerable]]等。
[[Prototype]]就是这个一个内部属性 , 它指的是对象的原型
脚本中没有访问这个[[Prototype]]特性的标准方式,但Firefox、Safari和Chrome会在每个对象上暴露__proto__属性,通过这个属性可以访问对象的原型

Prototype
3. 原型

任何对象都有原型,原型也是一个对象,其他对象可以通过它实现集成,每个原型自身又有一个原型,直到最顶端的Object。
__proto__属性为实例指向原型对象的指针,每个对象多有这个属性。
如下图所示,product的原型为Object,Object的原型是null,因为Object为原型链的顶端

let product = {
     name: '笔记本',
     price: 5999
}
原型
4. prototype

每个函数(对象上没有prototype属性)都会创建一个prototype属性,被称为原型对象,这个属性是一个对象,包含应该由特定引用类型的实例共享的属性和方法。实际上,这个对象就是通过调用构造函数创建的对象的原型。使用原型对象的好处是,在它上面定义的属性和方法可以被对象实例共享。

function Person() {}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function() {
  console.log(this.name);
};

let person1 = new Person();
person1.sayName(); // "Nicholas"

let person2 = new Person();
person2.sayName(); // "Nicholas"

console.log(person1.sayName == person2.sayName); // true
prototype
5. constructor

constructor属性始终指向创建当前对象的构造函数,任何一个对象都有constructor属性,指向创建这个对象的构造函数。
constructor 原型对象中包含这个属性,实例当中也同样会继承这个属性
默认情况下,所有原型对象自动获得一个名为constructor的属性,指回与之关联的构造函数。Person.prototype.constructor指向Person。然后,因构造函数而异,可能会给原型对象添加其他属性和方法。

constructor
6. 原型链

每个构造函数都有一个原型对象,原型有一个属性指回构造函数,而实例有一个内部指针指向原型。如果原型是另一个类型的实例呢?那就意味着这个原型本身有一个内部指针指向另一个原型,相应地另一个原型也有一个指针指向另一个构造函数。这样就在实例和原型之间构造了一条原型链。这就是原型链的基本构想。

function SuperType() {
    this.property = true;
}

SuperType.prototype.getSuperValue = function () {
    console.info(this.property);
    return this.property;
}

function SubType() {
    this.subproperty = false;
}

SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function () {
    console.info(this.subproperty);
    return this.subproperty;
}

let subTypeInstance = new SubType();
subTypeInstance.getSubValue(); //false

默认情况下,所有引用类型都继承自Object,这也是通过原型链实现的。任何函数的默认原型都是一个Object的实例,这意味着这个实例有一个内部指针指向Object.prototype。这也是为什么自定义类型能够继承包括toString()、valueOf()在内的所有默认方法的原因。

上一篇下一篇

猜你喜欢

热点阅读