XXHolic / segment

some notes
MIT License
28 stars 4 forks source link

instanceof #87

Open XXHolic opened 4 years ago

XXHolic commented 4 years ago

引子

碰到有关 instanceof 方法的问题一时想不起来,查了下资料,把相关的概念聚合了一下。

instanceof

在 MDN 上的解释是:

用于检测构造函数的 prototype 属性是否出现在某个对象的原型链上。

在这一句解释中,需要理解的概念有:

在 JavaScript 中除了自带的一些构造函数(例如 String()),当对一个自定义函数使用 new 表达式时,那么这个自定义函数同样可以称为构造函数。

函数有一个特有的属性 prototype ,翻译中文叫原型,这个属性的值是一个对象,存放了对象共有的属性和方法。

使用构造函数创建的对象,会有一个私有的属性 __proto__ ,它指向的是构造函数的 prototypeprototype 对象也有一个自己的属性 __proto__ ,就这样层层指向,直到一个对象的 __proto__ 为 null ,这些就形成了原型链。由于原型链,当在寻找对象中的某个属性时,首先在对象自身查找是否有该属性,如果没有,就会沿着 __proto__ 继续查找下去。

const a = new String(1);
console.log(a.__proto__.__proto__.__proto__)

// null

示例

根据上面的解释,结合具体的代码看看。

function A() {}

const obj1 = new A();
console.info(obj1 instanceof A);
console.info(obj1 instanceof Object);

A.prototype = {}

console.info(obj1 instanceof A)
结果 ```js true true false ``` 按照 `instanceof` 的方法说明,第一个打印结果是符合预期的,为了进一步确认,可以使用 `Object.getPrototypeOf()` 获取 `__proto__` 的值,再跟构造函数的 `prototype` 属性进行对比。 ```js function A() {} const obj1 = new A(); Object.getPrototypeOf(obj1) === A.prototype ``` 按照上面原型链查找的方式,只要判断一下构造函数 `Object` 的 `prototype` 属性是否在 `A.prototype` 对象上: ```js function A() {} const obj1 = new A(); A.prototype instanceof Object // true ``` 因此第一个打印结果为 true 。 后面直接修改了函数 `A` 的 `prototype` 属性,同样使用 `getPrototypeOf` 方法进行判断: ```js function A() {} const obj1 = new A(); A.prototype = {}; Object.getPrototypeOf(obj1) === A.prototype //false ``` 因此最后打印结果是 `false` 。也可以在控制台打印出来查看。
console.log(String instanceof String);
console.log(Object instanceof Object);
console.log(Function instanceof Function);
console.log(Function instanceof Object);
结果 ```js false true true true ``` 按照理解,后面三个结果都可以符合预期。但第一个结果为什么会是 `false` ?还是用方法 `getPrototypeOf()` 看下 ```js console.log(String instanceof String); console.info(Object.getPrototypeOf(String)); console.info(String.prototype); console.log(Function instanceof Function); console.info(Object.getPrototypeOf(Function)); console.info(Function.prototype); console.log(String instanceof Function); ``` 看了上面的打印结果,就会明白基于 `String` 对象原型链查,找到了 `Function` 那里了,所以 `String.prototype` 不在 `String` 的原型链上。

参考资料

:wastebasket: 突然想看动画电影,想到的是[《蜘蛛侠:平行宇宙》][url-artist],虽然之前看过,但再次看时,还是觉得很精彩,一部电影时长,将人物的喜怒哀乐及成长都表现出来,塑造了一个朝气少年的蜘蛛侠。里面的配乐也是很精彩,在蜘蛛侠从之前不敢跳下的高楼一跃,让我的内心再次也跟着澎湃了起来。 ![73-poster][url-local-poster]