关于原型链:一文彻底搞懂原型链

前言原型和继承是js中十分重要的两大概念。深刻理解原型,也是学好继承的前提。 先来看一下构造函数、实例、原型对象之间的关系 「实例与原型对象之间有间接的分割,但实例与构造函数之间没有。」 两个概念js分为「函数对象」和「一般对象」,每个对象都有__proto__属性,然而只有函数对象且「非箭头函数」才有prototype属性。 属性__proto__是一个对象【实例通过__proto__隐式原型指向其原型对象】,它有两个属性,constructor和__proto__;原型对象有一个默认的constructor属性,用于记录实例是由哪个构造函数创立; 原型了解原型创立一个函数(非箭头函数),就会依照特定的规定为这个函数创立一个 prototype 属性(指向原型对象)。默认状况下,所有原型对象主动取得一个名为 constructor 的属性,指回与之关联的构造函数。在自定义构造函数时,原型对象默认只会取得 constructor 属性,其余的所有办法都继承自Object。每次调用构造函数创立一个新实例,这个实例的外部[[Prototype]]指针就会被赋值为构造函数的原型对象。脚本中没有拜访这个[[Prototype]]个性的规范形式,但 Firefox、Safari 和 Chrome会在每个对象上裸露__proto__属性,通过这个属性能够拜访对象的原型。 function Person() {}// 阐明:name,age,job这些本不应该放在原型上,只是为了阐明属性查找机制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()let person2 = new Person()// 申明之后,构造函数就有了一个与之关联的原型对象console.log(Object.prototype.toString.call(Person.prototype)) // [object Object]console.log(Person.prototype) // {constructor: ƒ}// 构造函数有一个 prototype 属性援用其原型对象,而这个原型对象也有一个constructor 属性,援用这个构造函数// 换句话说,两者循环援用console.log(Person.prototype.constructor === Person); // true// 构造函数、原型对象和实例是 3 个齐全不同的对象console.log(person1 !== Person); // true console.log(person1 !== Person.prototype); // true console.log(Person.prototype !== Person); // true// 实例通过__proto__链接到原型对象,它实际上指向暗藏个性[[Prototype]] // 构造函数通过 prototype 属性链接到原型对象,实例与构造函数没有间接分割,与原型对象有间接分割,前面将会画图再次阐明这个问题console.log(person1.__proto__ === Person.prototype); // true conosle.log(person1.__proto__.constructor === Person); // true// 同一个构造函数创立的两个实例,共享同一个原型对象 console.log(person1.__proto__ === person2.__proto__); // true// Object.getPrototypeOf(),返回参数的外部个性[[Prototype]]的值 ,用于获取原型对象,兼容性更好console.log(Object.getPrototypeOf(person1) == Person.prototype); // true复制代码如下图: ...

March 12, 2022 · 2 min · jiezi