精华 用 Node.js 實現一個 Singleton
发布于 10 年前 作者 XadillaX 7319 次浏览 最后一次编辑是 8 年前 来自 分享

原文链接:http://xcoder.in/2014/09/30/javascript-singleton/

今天隨便玩了一道 CodeWar 的題

題意大致就是你需要實現一個 Singleton 也就是單件模式的類,讓其下面代碼執行成功:

var obj1 = new Singleton();
var obj2 = new Singleton();
obj1 === obj2; // => true
obj1.test = 1;
obj2.test; // => 1

並且還有很重要的一點就是 Singleton 的對象的 instanceof 也得的確是 Singleton 才行。

開始試驗

我們猜想 new Singleton() 的結果,如果 Singleton 函數也就是這個類的構造函數沒返回值的話,直接會返回 this,有返回值的話,那麼就是等於其返回值了。

我們碼下面的代碼看一下:

var Singleton = function() {
    return { foo: "bar" };
};

console.log(new Singleton());

跑一遍之後我們的確發現了輸出的值就是:

{ foo: "bar" }

小作弊失敗

於是我這麼做:

var foo = {};
var Singleton = function() {
    return foo;
};

結果上面的幾個條件都符合了,不信大家可以自己輸出一遍看看。

但是——

這東西不是一個 Singleton 的實例,它只是一個簡單的 JSON 對象,所以還是無法通過。

死月の正解

答案有很多,CodeWar 上面每個人的解法都不一樣,但是歸根結底本質還是大同小異的。

就是第一次的時候先直接返回 this,並且把 this 放在某個地方。以後每次來這裏創建的時候返回之前存好的 this 即可:

var Singleton = function() {
    if(Singleton.prototype.instance) return Singleton.prototype.instance = this;

    // Do some initialize things
    // ...

    Singleton.prototype.instance = this;
    return this;
};

別的寫法

寫法很多,我這裏隨意挑幾個別人的答案吧。

/**
 * By tjwudi
 */
var Singleton = function(){
  return Singleton.ins = Singleton.ins ? Singleton.ins : this;
};
/**
 * By nonowarn
 */
var Singleton = (function () {
  var instance = null;

  return function(){
    return instance || (instance = this);
  };
})();
12 回复

… 0. 0 咦,我怎么好像收到了一个回复,然后又不见了?

别人都是把 instance 放在构造函数上的,为什么你要放在构造函数的 prototype 上? 文中 nonowarn 的答案我觉得最好。

@xadillax 因为我删了,刚才写了个失败的…

@alsotang 我知道别人是 this.constructor.instance,但是不知道为什么要放在这里,constructor 是一个构造函数,在函数里面加点连接一个子对象感觉语义上很奇怪。

所以我觉得还是把它放在 this 内部比较好,可以直接用 this.instance 去调用(虽然本身就是)。

毕竟在别的语言比如说 C++ 的话,都是在类的内部有个私有的 static 的子对象,而不是类的构造函数里面又一个。

所以我觉得这样可能更符合语义吧。

不过各有各的习惯和理解,我发出来也只是抛砖引玉而已。

@xadillax 函数是第一公民,函数也是对象。在对象上赋个子对象挺正常的嘛。

@alsotang 其实我还是有意无意把它们语义上区分的。可能是受以前其它语言毒害太深吧。

注册codewar刷了几道题

就这个一句话…心中顿时一万个草呢吗呀呀呀… 2014-10-04_20-40-39.jpg

哎呀,这网站,碰到一个题,写了半天… 判断几点共线,function onLine(points){ … } http://www.codewars.com/kata/points-on-a-line/solutions/javascript

function onLine(points) {

  // 去重
  var _points = [];
  _points.has = function(search){
    return this.reduce(function(ret,p){
      return ret || (p[0] === search[0] && p[1] === search[1])
    },false)
  }
  points.forEach(function(p){
    if(!_points.has(p)){
      _points.push(p)
    }
  })
  
  // points 不重复
  points = _points
  if(points.length < 3) return true
  
  // y = kx + b
  // y1 = kx1 + b
  // y2 = kx2 + b
  var x1 = points[0][0]
  var y1 = points[0][1]
  
  var x2 = points[1][0]
  var y2 = points[1][1]
  
  var filter;
  
  if(x1 == x2){
    filter = function(x,y){
      return x === x1;
    }
  }
  else if(y1 == y2){
    filter = function(x,y){
      return y === y1
    }
  }
  else{
    var k = (y2 - y1)/(x2 - x1)
    var b = y1 - k * x1
    
    filter = function(x,y){
      return y === k*x + b
    }
  }
  
  for(var i = 2;i< points.length;i++){
    var x = points[i][0]
    var y = points[i][1]
    if(!filter(x,y) ) return false
  }
  
  return true
}

前阵子看了设计模式和对象的一些操作,除了有限状态机(严格来说不算设计模式吧)其他的真没联想到实际工作中的应用场景,同事说是写框架时可以用到,但想来想去也只有观察者

@klamtlne 如果想拿 js 写游戏还是有一定应用场景的。包括服务端和客户端。

这个 tjwudi 貌似是阿里的?

试验失败是因为你返回的只是字面量声明的对象吧,实际上相当于 return new Object(…),被表象迷惑了

回到顶部