对原型链的理解
最近每天的主要任务都是在准备面试题,经过上次卓动的面试感觉自己的基础还是很薄弱的,在看了 new 操作符的时候用到了对象原型这一概念后,我就觉得有必要先把原型链给弄明白来。
什么是原型?
原型链字面意思就是原型的链,那自然就离不开原型。何为原型?简单来说,原型是一个普通的对象,这个对象有一个 constructor
属性,指向该对象的构造函数,同时原型上可以有一些属性和方法。为了更好地理解什么是原型,这里先引入使用 class
实现继承,学过 Java 都可以直接理解,示例代码如下:
class Person {
constructor(name) {
this.name = name;
}
}
class Student extends Person {
constructor(name, age) {
super(name);
this.age = age
}
study() {
console.log(`${this.name}正在写代码`);
}
}
let student = new Student('PandaGuo', 22);
console.log(student.name); // PandaGuo
student.study(); // PandaGuo正在写代码
如上述代码所示,Student
类继承了父类 Person
,最终 new 出来的 student
对象可以访问到 name
属性,也可以访问到 study()
方法,但是在控制台上打印出 student
对象却没有发现 study()
方法:
继续展开下面的 [[Prototype]]
其实就可以找到相应的 study()
方法:
这是因为 studnet 对象中如果找不到相应的 study() 方法,那么它就会往它自身的 _proto_
中寻找相应的方法。这里打印出 student._proto_
可以发现结果是一个对象:
而我们再试着打印出 Student 类中的 prototype 可以发现也是一个与之相同的对象:
继续在控制台上对二者进行比较,发现返回值为 true,说明二者指向的是同一个对象:
这时候我们可以根据上述的结果画出这样一张图:
由图可知,每一个对象都有一个原型 _proto_
,一般叫做隐式原型,这个隐式原型会指向构建该对象的类的显示原型,也就是prototype
,当对象查找不到需要的属性或方法的时候,会在它自身的隐式原型 _proto_
上继续查找。
什么是原型链?
像刚刚上图所示,如果我在 student 对象中需要找到一个 play() 方法,而这个 play() 方法一开始是定义在 Person 类当中,那么 student 就会在它原型的原型当中去找这个类,具体图例如下所示:
如果 student 对象又调用了某个属性或方法且不存在于 Person 类当中,那么和上面一样,以此类推,又会到 Person 的原型当中去寻找,这种搜寻轨迹形似一条长链,且 prototype 在这条链当中充当了连接的作用,所以我们将这种实例与原型链条命名为原型链。如果找不到对应的属性或方法,实例对象会一直在这条原型链中继续往下寻找,直到找到或者到达顶端位置,而原型链的顶端是 Object.prototype 对象,对应的值是 null:
而如果需要判断某个对象或者方法是否为自身所拥有的,可以用 hasOwnProperty()
方法来检测,如果是,则返回 true
, 否则返回 false
。
instanceof 运算符
instanceof
运算符可以用于检查一个对象是否是某个特定类型的实例。其具体的实现过程也涉及到了原型链,语法结构为:" A instanceof B ",在判断时会在原型链中递归查找 A._proto_
是否等于 B.prototype
,如果整条原型链都没有找到符合条件的类型则返回 false
,相反则返回 true
。
instanceof
一般可以用来判断 Array
和 Object
,具体代码如下:
let arr = [];
let obj = {};
console.log(typeof arr); // object
console.log(typeof obj); // object
/* 直接使用 typeof 判断 数组和对象不可行,二者的返回结果都是 Object */
/* 而使用 instanceof 就可以区分二者 */
console.log(arr instanceof Array); // true(因为 arr 本身是数组,在 Array.prototype 中可以找到相应的实例)
console.log(obj instanceof Array); // false(obj 本身是对象,在 Array.prototype 中找不到相应的实例)
参考资料: 3原型链哔哩哔哩_bilibili