当我们用new运算符new一个构造函数产生一个实例时,比如说: var obj = new Func 时,其背后的步骤是这样的:
1:创建一个继承自 Func.prototype 的新对象;
2:执行构造函数 Func ,执行的时候,相应的传参会被传入,同时上下文(this)会被指定为第一步创建的新实例;
3:如果构造函数返回了一个“对象”,那么这个对象会取代步骤1中new出来的实例被返回。如果构造函数没有返回对象,那么new出来的结果为步骤1创建的对象。
注意:new Func 等同于new Func(),只能用在不传递任何参数的情况。
按照上述原理,写一段代码模拟new运算符的实现原理:
//new运算符原理实现 var new1 = function(fun){ var newObj = Object.create(fun.prototype); var returnObj = fun.call(newObj); if(typeof returnObj === 'object'){ return returnObj }else{ return newObj } }
其中 var newObj = Object.create(fun.prototype) 的意思是:创建一个新对象newObj,并让 newObj.__proto__ 指向 fun,即 newObj.__proto__ === fun 返回true。
测试一下~
var strObj = new1(String); alert(strObj instanceof String); //true alert(strObj.__proto__.constructor === String); //true
可以看到,new1函数的运行效果和new运算符是一样的。我们继续给String的原型上添加一个方法,看看new1函数得到的strObj能否继承到这个方法:
String.prototype.defineByN = function(){ alert("我是自定义方法"); } strObj.defineByN(); //弹出“我是自定义方法”
可以看到new1函数得到的strObj继承了到这个方法。