记录一下自己理解的 new
和 instanceof
,实现一遍加深理解和记忆。
new
操作符
先从一个例子中看 new
操作符做了什么
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| function Person(name) { this.name = name }
Person.prototype.say = function () { console.log(`${this.name}已经吃了晚饭🥣`) }
const personName = new Person('张三')
personName.name personName.say()
personName.__proto__ === Person.prototype Object.getPrototypeOf(personName) === Person.prototype
|
分析:首先实例的 .
访问的特性可以知道 new
最终 return
的是一个对象的类型,因此需要做一个判断,如果原来构造函数有 Object
类型的返回值,我们是不可以动的,也就是需要直接返回,如果不是 Object
类型的类型的话就要返回我们所创建的对象,所以必须先创建一个空的对象,作为在原来构造函数没有 Object
类型的情况下的返回值。然后发现实例具有一些可以访问构造函数的 prototype
的能力,而且是具有参数的绑定,并且我们知道实例的 __proto__
等于构造函数的 prototype
。
大概实现应该如下:
1 2 3 4 5 6 7 8 9 10 11 12 13
| function myNew(Fn, ...args) { const obj = {} obj.__proto__ = Fn.prototype
const result = Fn.apply(obj, args)
const isObject = typeof result === 'object' && result !== 'null'
return isObject ? result : obj }
|
验证一下正确性:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| function Person(name) { this.name = name }
Person.prototype.say = function () { console.log(`${this.name}已经吃了晚饭🥣`) }
const personName = myNew(Person, '莉莉丝') personName.name personName.say()
personName.__proto__ === Person.prototype Object.getPrototypeOf(personName) === Person.prototype
|
instanceof
操作符
我们都知道 instanceof
操作符是可以判断一个数据的类型,但是只能判断非简单的数据类型,继续以一个例子来看。
1 2 3 4 5 6 7 8 9 10
| const obj = { name: '张三' } const arr = ['张三'] const time = new Date()
obj instanceof Object obj instanceof Date arr instanceof Array time instanceof Date
|
分析:可以从上面的例子发现,操作符右边的就是构造函数,左边就是构造函数的实例,而构造函数和实例之间的关系即就是 instance.__proto__ === Fn.prototype
,但是根据作用域链的就近原则不能保证就近能找到对应的关系链所以必须要一步一步往原型链上找,找到的话就可以返回 true
,我们知道原型链的顶端为 null
,当为 null
的时候即没找到应该返回 false
。
具体实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| function myInstanceof(left, right) { const isObject = typeof left === 'object' && left !== 'null' if(!isObject) { return false }
let proto = Object.getPrototypeOf(left)
while(true) { if(proto == null) { return false }
if(proto == right.prototype) { return true }
proto = Object.getPrototypeOf(proto) } }
|
1 2 3
| function myInstanceof(left, right) { return left !== null && (Object.getPrototypeOf(left) === right.prototype || myInstanceof(left, right)) }
|
验证:
1 2 3 4 5 6 7 8
| var obj1 = { name: '张三' } var arr1 = ['张三'] var time1 = new Date()
console.log(obj1 instanceof Date, arr1 instanceof Array, time1 instanceof Date)
|