instanceof
原理
其实 instanceof
主要的实现原理就是只要右边变量的 prototype
在左边变量的原型链上即可。
因此,instanceof
在查找的过程中会遍历左边变量的原型链,直到找到右边变量的 prototype
,如果查找失败,则会返回 false,告诉我们左边变量并非是右边变量的实例。
手写 instanceof
instanceof
就是判断构造函数的 prototype
属性是否出现在实例的原型链上。
function instanceOf(left, right) { let proto = left.__proto__ while (true) { if (proto === null) return false if (proto === right.prototype) { return true } proto = proto.__proto__ } }
上面的 left.proto
这种写法可以换成 Object.getPrototypeOf(left)
。
function instance_of(L, R) { // L 表示左边表达式 R 表示右边表达式 const O = R.prototype; // 取 R 的显式原型 L = Object.getPrototypeOf(L); // 取 L 的隐式原型 L = L.__proto__ while(true) { // Object.prototype.__proto__ === null if(L===null) { return false; } if(L===O) { // 当 L 严格等于 O 时,返回 true return true; } L = Object.getPrototypeOf(L); // // 没找到继续向上一层原型链查找 L = L.__proto__ } } function Foo(name) { this.name = name; } var f = new Foo('nick') f instanceof Foo // true f instanceof Object // true
new
new
运算符用来创建用户自定义的对象类型的实例或者具有构造函数的内置对象的实例。
实现要点:
new
会产生一个新对象;- 新对象需要能够访问到构造函数的属性,所以需要重新指定它的原型;
- 构造函数可能会显示返回;
手写 new
function objectFactory() { var obj = new Object() Constructor = [].shift.call(arguments); obj.__proto__ = Constructor.prototype; var ret = Constructor.apply(obj, arguments); // ret || obj 这里这么写考虑了构造函数显示返回 null 的情况 return typeof ret === 'object' ? ret || obj : obj; };
function _new(constructor, ...args) { // 构造函数类型合法判断 if(typeof constructor !== 'function') { throw new Error('constructor must be a function'); } // 新建空对象实例 let obj = new Object(); // 将构造函数的原型绑定到新创的对象实例上 obj.__proto__ = Object.create(constructor.prototype); // 调用构造函数并判断返回值 let res = constructor.apply(obj, args); let isObject = typeof res === 'object' && res !== null; let isFunction = typeof res === 'function'; // 如果有返回值且返回值是对象类型,那么就将它作为返回值,否则就返回之前新建的对象 return isObject || isFunction ? res : obj; };