原型和原型链理解起来竟如此简单!!!
理解
我们在理解原型和原型链的时候,喜欢去看他们的概念,而概念又非常晦涩难懂,常常刚明白了这个名词,又出现一个新的名词,然后又发现之前理解的有问题,又倒回去理解,往复如此,搞得自己晕头转向,理解能力强的人自然不怕,但大部分人理解能力有限,容易混淆概念,这是因为我们头脑里没有形成具体的事物或者说一张图,来描述各个事物之间的联系,你没有固定的参考对象,所以难理解。不妨我们反着来,先搞定参考对象,再来看定义,也许会轻松许多。
// 添加方法到原型对象
Person.prototype.sayHello = function() {
console.log(`我是原型对象`);
};
// 构造函数
function Person(name) {
this.name = name;
}
// 创建实例
const person = new Person('Alice');
如图关系:
-
Person Prototype是原型对象
-
Person是函数
-
person是实例对象
每个函数都有一个prototype
属性,相当于指针,这个指针指向函数的原型对象,即Person.Prototype。
在默认情况下,所有原型对象都会自动获得一个constructor
属性,相当于指针,这个指针指向prototype属性所在函数即Person。
实例对象即person,都会有一个属性proto (谷歌上显示的是 [[Prototype]] ),相当于指针,这个属性会指向该对象的原型即Person.Prototype。
简化一下,得如下图:
因此会得到如下的关系:
function Person() {
}
var person = new Person();
console.log(person.__proto__ == Person.prototype) // true
console.log(Person.prototype.constructor == Person) // true
console.log(Object.getPrototypeOf(person) === Person.prototype) // true
当找不到实例属性时,就会查找与对象关联的原型中的属性,如果还查不到,就去找原型的原型,一直找到最顶层为止。我们称这样一个路径为原型链,顺着链子找属性,直到找到Object的原型对象(Object.prototype)为止,(原型对象就是通过 Object 构造函数生成的,所以就到顶了),如果没找到就显示undefined。
你也可以打印一下看看Object.prototype
是否真的没有原型了:
console.log(Object.prototype.__proto__ === null) // true
等于null为true,所以真的没有了。
所以完整的关系图应该是类似这样的:
综上,我们称 prototype 为显示原型,proto 为隐式原型。
使用原型对象的好处是可以让所有对象实例共享它所包含属性和方法。(理解为人类这个对象都共享一个大脑属性,即都有一个脑袋,没有谁没有)
小tips:可以把prototype和__proto__看成血脉,天生就有,凭着血脉,就可以找到亲生父亲,这样就更好理解了。
看懂后,你就可以去看书上的概念了,相信你会有不同的感悟!
面试题补充:
所有对象都有原型吗?
显然最顶端的对象Object.prototype
就没有原型了,上面已经解释清楚了,在这里提一嘴是因为真的很容易忘记!!!
接上篇文章
如下: 1.如果访问不存在的属性,为什么出现的是undefined,而不是报错?
解释:因为在当前的原型对象找不到时,就会沿着原型链往上找,一直到顶,还没找到就返回undefined,而不是报错。
2.补充的步骤
当执行引擎把原始类型错看成对象时,接下来是沿着原型链找属性,结果没找到,回来时,发现原来是原始类型,所以就删除 之前把原始类型当成对象 的行为。
转载自:https://juejin.cn/post/7366899841454194698