当谈到继承的时候,JavaScript 只有一种数据结构:对象,每个实例对象(Object)都有一个私有属性(称之为 __prpto__ ),指向它的构造函数的原型对象( prototype ),该原型对象也有一个他自己的原型对象( __proto__ ),层层向上直到一个对象的原型为 null。根据定义 null 没有原型,并作为这个原型的最后一个环节。
几乎所有的 JavaScript 中的对象都是位于原型链顶端的 Object 的实例。
JavaScript 对象有一个指向一个原型对象的链。当试图访问一个对象属性的时候,它不仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或者达到原型链的末尾。
遵循 ECMAScript 标准,someObject.[[Prototype]] 符号是用于指向 someObject 的原型。从 ECMAScript 6 开始,[[Prototype]] 可以通过 Object.getPrototypeOf () 和 Object.setPrototypeOf () 访问器来访问。这个等同于 JavaScript 的非标准但是许多浏览器已经实现的属性 __proto__。
举个?
function Person() {
this.name = 'tom';
this.age = 20;
}
const p = new Person();
// 在构造函数的原型上定义属性Person.prototype.gender = '男';Person.prototype.name = 'felling';
注意:
-
不做在构造函数的原型上直接定义 Person.prototype = {gender : '男'};这样会打破原型链;
-
p.[[Prototype]] 上有属性 gender,其实就是 p.__proto__ 或者 p.constructor.prototype
-
p.__proto__ 是 Person.prototype;
-
p.__proto__.__proto__ 是 Object.prototype;
-
最后 p.__proto__.__proto__ 是 null,这就是原型链的末尾 null;
-
根据定义 null 就没有 __proto__ ;
-
综上:整个原型链如下:
{name: 'tom', age: 20} -> {gender: '男'} -> Object.prptotype --> null
.
console.log(p.name);
// name 是 p 的自身属性吗?是的,该属性值为 'tom'
// 原型上也有一个属性 name ,但是他不会被访问到,这种情况称之为属性遮蔽
console.log(p.company);
// company 是 p 的属性吗?不是,那么看看他的原型上有没有
// company 是 p.proto(即 Person.prototype) 的属性吗?不是,那么看看他的原型上有没有
// company.proto.proto (即Object.prototype)也没有 company
// company.proto.proto.__proto 为 null 停止搜索
// 找不到属性 company 返回 null
在控制台我们可以看到 Person 构造函数的 prototype 打印结果如下:
在控制台我们可以看到 p 打印结果如下:
-
如上图所示, p 中的 __proto 是 Person.prototype 。但是为什么这么做?当我们访问p 中的一个属性的时候,浏览器首先会查看 p 中是否有这个属性;
-
如果 p 中不包含这个属性,那么浏览器会在 p 的 __proto__ 中进行查找(Person.prototype),如果在 p 的 __proto__ 中找到,则使用 p 的 __proto__ 中的属性;
-
否则,如果 p 的 __proto__ 不具有改属性,则检查 p 的 __proto__ 的 __proto 是否具有改属性, 默认情况下,任何函数原型属性 __proto__ 都 window.Object.prototype。因此 通过 p 的 __proto__ 的 __proto__ (桶Person.prototype 的 __proto__ 或者 Object.prototype)来查找要搜索的属性;
-
如果属性不存在 p 的 __proto__ 的 __proto__ 中,那么就会在 p 的 __proto__ 的 __proto__ 的 __proto__中进行查找。然而这里存在一个问题:p 的 __proto__ 的 __proto__ 的 __proto__ 其实不存在,因此,只有这样 在 __proto__ 的整个原型链被查看之后,这里没有更多的 __proto__ ,浏览器断言该属性不在,并给出该属性的值为 undefined的结论。
最后附上一张图:
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!