什么是原型链
什么是原型链?
JS里每个对象都有一个原型,在chrome浏览器里可以认为是属性 __proto__,指向的是这个对象的构造函数的 prototype 属性(在JS里函数也是对象的一种所以可以有属性)。
而这个原型也是一个对象,那作为对象,它又有一个原型,又是对象,又有原型,如此说来似乎子子孙孙无穷尽也。然鹅事实并非如此。
举例,let a = {},则 a.__proto__ === Object.prototype,因为 a 作为一个字面量对象,构造函数是 Object(),则 属性 a.__proto__ 指向构造函数 Object.prototype,容易理解。
然鹅,a.__proto__.__proto__ === null,就成立了,为何?不是说 a.__proto__ 是 Object.prototype 对象吗?既然是对象,那构造函数应当还是 Object,那么 a.__proto__.__proto__ 就应该还是指向 Object.prototype 才对,为什么不是呢?
说到底,JS为什么要设计这么一套原型和原型链体系?是为了实现继承!是为了聚合公用的共有的属性和方法。不是为了原型而原型。
具体的说,是为了当通过对象 a 访问其属性 xxx 或者方法 xxx 时,如果 a 本身没有此方法/属性,则去 a.__proto__ 里找,如果还不存在,则到 a.__proto__.__proto__ 里找,既然是要找,那么说明肯定不是大海捞针,肯定需要找的范围是可以预见的,确定的。
所以,如果 a 是普通字面量对象,那么 a.__proto__.__proto__ 就需要是null了。
想想如果不是如此会怎样,如果 a.__proto__.__proto__ === a.__proto__ === Object.prototype,那么当 a 里不包含 xxx 属性/方法时,到 a.__proto__ 里找,还找不到则到 a.__proto__.__proto__里找。
然鹅,a.__proto__ 和 a.__proto__.__proto__ 是同一个东西,相当于你在一间房子里找一只袜子找了一遍,没找到,又找了一遍,看起来还要再找一遍而且会不停的找下去不停的找不到,你完了。
所以,JS里和对象相关的公共的属性/方法,就都放在 Object.prototype 里了,它是一个特殊的对象,它的 __proto__ 是 null。所以 a.__proto__.__proto__ === null。
至于这个对象怎么来的?JS里也可以手动创建这种 __proto__ 是 null 的对象:Object.create(null)。