New操作符实现原理
为了方便测试与理解,我们先来创建一个构造函数
function Point(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
}
然后调用我们自己封装的new方法,可以看到实例化对象可以正常打印。
var p = objectFactory(Point, 5, 2, 3)
console.log(p);
再详细介绍它的实现原理之前,需要先理解以下几个方法:
1.Object.creat()
它的官方解释:创建一个新对象,使用现有的对象来提供新创建的对象的proto。
var obj=null
obj=Object.create(Point.prototype)
console.log(obj.__proto__===Point.prototype); //true
在这里,我们做了两件事:
1.新建了一个空对象obj
2.利用Object.create()的方法,将构造函数的prototyoe指向空对象obj的__proto__
2.Array.from()
Array.from()是ES6新增的方法,可以将类数组转化为真正的数组。因为类数组虽然具有索引和length等属性,但无法调用数组API。
当然,比较常用的apply、arguments这些用法就不过多阐述了。如果这些还不熟悉的我相信也不会来看实现原理这些。。
那下面就开始正式实现我们自己的NEW方法了。
function objectFactory() {
//1.创建一个空对象
let newObject = null;
let arr = Array.from(arguments) //将函数参数转化为数组
let constructor = arr.shift() //拿到数组的第一个参数:构造函数
let result = null;
// 2.将构造函数的 prototype指向新对象的proto属性
newObject = Object.create(constructor.prototype);
//3.将 this 指向新建对象,并执行函数
result = constructor.apply(newObject, arr);
// 判断返回对象
let flag = result && (typeof result === "object" || typeof result === "function");
// 4.判断返回结果
return flag ? result : newObject;
}
1.首先,创建了空对象newObject:在这个阶段我们将传入的参数对象arguments利用Array.from()转化为了数组。利用shift()弹出了数组的第一个元素,也就是传入的构造函数这个参数。并保存到了变量constructor里。
2.利用Object.create(),将我们上一步拿到的构造函数的prototype指向了新创建的对象newObject
3.通过apply()改变了this指向:此时的this指向了我们新创建的对象newObject。由于第一步时保存了所有参数的arr数组使用过了shift(),所以此时第一个元素(构造函数)已经被弹出,arr里剩下的都是实例化的参数。所以我们将arr作为apply的第二个参数传入,并执行函数。
4.返回最后的结果:由于我们传入的函数不一定都是构造函数,也有可能是一个普通函数。所以需要对最后的结果作一些判断处理。如果返回的是对象或者函数,最后的结果就等于result;如果返回是是基本类型的值,就让它等于这个newObject对象。假设我们取消最后判断,直接输出最后的结果result,执行以下函数
function test(a, b) {
return a+b
}
var t = objectFactory(test, 1, 4)
console.log(t); //5
这里我们传入的是一个普通函数,返回a+b的和。再使用了我们自定义的方法后,直接就输出了结果5,所以此时我们需要将最后的结果指向newObject。
上一篇: WPF SharpDx 性能优化方法
下一篇: WPF中Style样式及其触发器