js中的new做了什么?
通常,我们会这样回答:
new做了三件事
1、创建一个普通对象(简称obj);
2、将构造函数的prototype的地址引用赋给obj.__proto__属性;
3、将构造函数的this指向转移给obj后,返回obj对象;
上代码:
function Fun(){}
let f = new Fun();
console.log(f.__proto__ === Fun.prototype)//true
function imitateNew(){
let obj = {}; //创建一个普通对象(简称obj);
obj.__proto__ = Fun.prototype; //将构造函数的prototype的地址引用赋给obj的__proto__属性;
Fun.call(obj); //将构造函数的this指向转移给obj
return obj; //返回obj对象;
}
let fun = imitateNew();
console.log(fun.__proto__ === Fun.prototype)//true
好像没问题。
实际都是这样吗?
我们来看一个单例:
let Single = (function () {
let Singleton = function () { }; // 声明Singleton对象,无法在外部直接调用
let instance; // 声明一个instance对象
let other = {
name: 'other',
fun: 'as an example'
};
return function () {
if (instance) { // 如果已存在 则返回instance
return instance;
}
instance = new Singleton() // 如果不存在 则new一个
return instance;
}
}());
let a = new Single();
let b = Single();
console.log(a===b)//true
console.log(a.__proto__===Single.prototype)
猜猜看控制台分别打印了什么。
(a.__proto__===Single.prototype) === false 为什么?
为什么不是
我们看看函数对象Single,它是一个立即执行函数,在执行new Single()之前,立即执行函数已经执行完毕,立即执行函数中的other等未被引用的对象会被释放,看到instance,instance对象被返回,
并将地址引用赋给Head,即instance对象目前是被引用到的,所以浏览器暂时无法释放其内存空间,Singleton函数对象呢,会被instance.__proto__.constructor引用,所以浏览器也暂时无法释放其内存空间。
现在,我们可以知道,Single函数返回的是一个对象(instance),是一个由Singleton函数构造出来的对象,在立即执行函数作用域中,应有
(instance.__proto__ === Singleton.prototype)===true
,在执行a = new Single()之后,a就是这个instance的引用,所以,
(a.__proto__ === Singleton.prototype)===true
但由于作用域的原因,我们不能在外层这样进行判断打印输出,但我们可以换一种方法:
console.log(a.__proto__.constructor.name==='Singleton')//true
因此,console.log(a.__proto__===Single.prototype) 是false。
具体问题具体分析
后面有人问js中的new操作符做了什么,是不是要先回答:具体问题具体分析,要先看看构造函数有没有返回值,返回了什么……
^-^