原文链接: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);
};
})();
@alsotang 我知道别人是 this.constructor.instance
,但是不知道为什么要放在这里,constructor
是一个构造函数,在函数里面加点连接一个子对象感觉语义上很奇怪。
所以我觉得还是把它放在 this
内部比较好,可以直接用 this.instance
去调用(虽然本身就是)。
毕竟在别的语言比如说 C++ 的话,都是在类的内部有个私有的 static
的子对象,而不是类的构造函数里面又一个。
所以我觉得这样可能更符合语义吧。
不过各有各的习惯和理解,我发出来也只是抛砖引玉而已。
哎呀,这网站,碰到一个题,写了半天… 判断几点共线,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
}