为啥要用new: 在javascript中, 通过new可以产生原对象的一个实例对象,而这个实例对象继承了原对象的属性和方法。
new操作符干了什么:
- 创建一个新对象。
- 新对象隐式原型链接到构造函数显式原型。
- 执行构造函数并将构造函数作用域指向新对象。
- 返回新对象。
new的过程中遇到的坑一:
我们看到:new Function
返回的是一个函数, new Object
返回的是一个对象,那么什么是普通对象什么是函数对象? 通过查找资料发现有这么一句话:凡是通过 new Function()
创建的对象都是函数对象,其他的都是普通对象。
new的过程中遇到的坑二:
我们看到new一个普通对象报错,new一个函数对象才可以,对于这个结果很好奇为什么?于是又查资料。
原型对象:
1).显式原型: 每个函数对象都有prototype属性,称为显式原型2).隐式原型: 每个普通对象都有_proto_属性,指向的是相对应的构造函数的prototype,称为隐式原型复制代码
是不是可以这么理解,new一个普通对象,因为只有函数对象才有prototype
属性,所以普通对象无法通new来创建一个新对象。只有通过函数对象来用new创建一个新的普通对象。
分析上面步骤的具体内容:
- new就是根据一个a(函数)对象创建了一个新的b(普通)对象。
- b属于普通对象,那么就有
__proto__
属性,普通对象的__proto__
属性指向他的构造函数(函数对象)的prototype
,所以a是b的构造函数,b是a的实例对象。 - 通过执行构造函数给b对象添加属性,构造函数的this指向b对象。
具体实现步骤:
function _new (fn) { var obj = { __proto__ : fn.prototype, }; var res = fn.call(obj); return Object.prototype.toString.call(res) === "[object Object]" ? res : obj; }复制代码
我们来运行一下代码:
可以看到我们实现了new操作符所干的事。 但是有这种情况:var o3 = new fun ('tom');
,而且如果构造函数包含好几个属性,在new的过程中,有可能会传入多个参数。 我们需要改造一下: function _new (fn) { return function () { // 返回一个函数,调用此函数时传入的参数达到new带参数的目的。 var obj = { __proto__ : fn.prototype, }; var res = fn.apply(obj, arguments); return Object.prototype.toString.call(res) === "[object Object]" ? res : obj; }}复制代码
我们再来运行一下代码:
虽然没有像new那么简结,但是也算是实现了我们想要的。当然使用闭包的方式会有内存泄漏的风险!所以我们还可以改造一下:
function _new () { var fn = [].shift.call(arguments); //var ags = [].prototype.slice.call(arguments, 1); var obj = { __proto__ : fn.prototype, }; var res = fn.apply(obj, arguments); return Object.prototype.toString.call(res) === "[object Object]" ? res : obj;}复制代码完美! 如果上面分析有误,请及时在评论区指正,谢谢。