찾다

 >  Q&A  >  본문

javascript - js的单例模式,重写构造函数,为什么new了两次只执行了一次重写的那个构造函数

function Universe() {
    // 缓存的实例
    var instance = this;

    // 其它内容
    this.start_time = 0;
    this.bang = "Big";

    // 重写构造函数
    Universe = function () {
        alert(1)
        return instance;
        //改成return this,uni2.bang是undefined
    };
}

// 测试
var uni = new Universe();
var uni2 = new Universe();
uni.bang = "123";
console.log(uni === uni2); // true
console.log(uni2.bang); // 123

这里new了两次Universe(),只alert了一次1,为什么呢?
然后重写构造函数里,把 return instance;改成return this,uni2.bang是undefined,两个有什么区别呢?

ringa_leeringa_lee2773일 전289

모든 응답(4)나는 대답할 것이다

  • 大家讲道理

    大家讲道理2017-04-11 12:36:59

    你return instance 的时候,返回的是上面那个 Universe() 作用域内的this,所以可以获取到 this.bang

    Universe = function () {
        alert(1)
        // 这里返回的this 是当前这个 function作用域内的 this。没有任何属性
        return instance;
    };

    회신하다
    0
  • 阿神

    阿神2017-04-11 12:36:59

    第一次运行,返回了重写前的构造函数的实例————这种事普通的构造函数,只是函数内部重写了Universe,并且形成了一个闭包

    第二次运行,如果返回instance,就跟调用普通函数一样(这种方式类似于稳妥构造函数模式)。
    如果返回this,则就是又调用了一次普通的构造函数,返回一个{},其没有任何实例属性。

    회신하다
    0
  • 天蓬老师

    天蓬老师2017-04-11 12:36:59

    不知道题主知道原因没有,小白试着理解一波...
    首先,是var uni = new Universe();这一步先是用instance保存了Universe这个函数的this指向,instance一直留在内存里面,重写构造函数的时候不会执行alert(1)。这个重写相当于重新给一个已经声明了的变量赋值嘛,平时写完

    first:var a = function(){
        //do sth
    };
    second:a = function(){
        alert('sth');
    };

    也不会alert出东西吧。
    接着是var uni2 = new Universe();这个时候new的直接就是重写部分

    function Universe () {
        alert(1)
        return instance;
    };

    了,1也就因为Universe被new,如UKer所说“跟调用普通函数一样”alert出来了,然后接下来无论var uni[3456] = new Universe(); 1 也都会alert出来。

    而第二个问题,把instance改成this,uni还可以拿到指向原Universe的this,uni2因为重写之后this并不是指向原Universe,指向的是重写后的空的Universe {}。所以uni === uni2 //false。你uni.bang = "123";是给原Universe.bang赋值,而uni2里面啥都没有,所以无论uni2.start_time还是uni2.bang都是undefined

    表达能力一般,希望题主看完能理解~O(∩_∩)O~

    회신하다
    0
  • 黄舟

    黄舟2017-04-11 12:36:59

    为什么没人去质疑题主写的单例模式很奇怪呢?

    要是我希望内存只有一份数据,这样不是更简单吗?

    var Universe = {
        start_time: 0,
        bang: 'Big'
    };

    如果你觉得不够用,要加几个动作,可以这样:

    var Universe = {
        start_time: 0,
        bang: 'Big',
        doing: function() {}
    };

    假如你认为需要一些内部私有变量,可以写个标准的闭包。

    var Universe = (function() {
    
        var _name;
    
        function _getName() {
    
        }
    
        return {
            start_time: 0,
            bang: 'Big',
            doing: function() {},
            getName: _getName
        };
    
    })();

    优雅的语言,别整复杂了。

    회신하다
    0
  • 취소회신하다