js中的new做了什么?具体问题具体分析

169 阅读2分钟

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等未被引用的对象会被释放,看到instanceinstance对象被返回, 并将地址引用赋给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操作符做了什么,是不是要先回答:具体问题具体分析,要先看看构造函数有没有返回值,返回了什么……

^-^