js单例模式
window.onload = function() {
var CreateDiv=function(html){
this.html=html;
this.init();
}
CreateDiv.prototype.init=function(){
var div=document.createElement("div");
div.innerHTML=this.html;
document.body.appendChild(div);
}
//这个代理类为什么要用匿名函数自执行,写成普通函数为什么却没用?
var ProxySingletonCreateDiv=(function(){
var instance;
return function(html){
if(!instance){
instance=new CreateDiv(html);
}
return instance;
}
})();
var a=new ProxySingletonCreateDiv("sven1");
var b=new ProxySingletonCreateDiv("sven2");
alert(a===b);
}
jquer javascript闭包 JavaScript javascript面向对象
Answers
首先按照LZ说的把自执行去掉改成普通Function的闭包
var ProxySingletonCreateDiv=(function(){
var instance;
return function(html){
if(!instance){
instance=new CreateDiv(html);
}
return instance;
}
})();
var a=new ProxySingletonCreateDiv("sven1");
var b=new ProxySingletonCreateDiv("sven2");
alert(a===b); //这里输出false
好,false显然不能满足单例的要求,我们要把代码改成如下才能实现单例
var ProxySingletonCreateDiv=(function(){
var instance;
return function(html){
if(!instance){
instance=new CreateDiv(html);
}
return instance;
}
})();
var CreateDiv = new ProxySingletonCreateDiv();
var a= CreateDiv ("sven1");
var b= CreateDiv ("sven2");
alert(a===b); //这回输出了true 实现了单例
所以这里就有个问题,不使用自执行的方式实现单例就显得不够优雅。再解释区别之前,我们先来说说,用new来初始化一个function和直接调用一个function的区别。来看看下面的例子。
function A(){
this.user = {"name":"helloA"};
return this.user.name;
}
function B(){
this.user = {"name":"helloB"};
return this.user;
}
function C(){
this.user = {"name":"helloC"};;
return function(){
return this.user;
};
}
var a = new A();
console.log(a); //打印出完整的a对象,由于return是个字符串,被直接无视了
var a1 = A();
console.log(a1); //打印出helloA,这个很正常
var b = new B();
console.log(b); //打印出user对象{"name","helloB"},return的值因为是个对象,没有被无视,这点和function A不同
var c = new C();
console.log(c); //打印出return的 anonymous function,也没有被无视,和function A 不同
通过上面的例子我们可以看出,使用new关键字初始化的function会返回this对象,而无视return的值,除非
return的是一个对象,或者function
。 而直接使用Function()方式则直接返回return的值。
好了,讲到这里一些朋友可能已经看出题主的问题关键之所在了,他不是在问闭包的问题,而是new关键字的问题。
var ProxySingletonCreateDiv=(function(){
var instance;
return function(html){
if(!instance){
instance=new CreateDiv(html);
}
return instance;
}
})();
当我们使用自执行方式的时候其实 var ProxySingletonCreateDiv这个变量已经指向了这个自执行匿名函数的return值,也就是另外一个匿名函数
function(html){
if(!instance){
instance=new CreateDiv(html);
}
return instance;
}
即
var instance;
var ProxySingletonCreateDiv = function(html){
if(!instance){
instance=new CreateDiv(html);
}
return instance;
}
所以,再后面的2次new关键字的使用,其实你new的是上面这个return的匿名函数,由于这个匿名函数本身是return的是一个实例,所以你使用了new关键字也不会影响到它的返回(参见上面的function C()例子 )。因为instance这个变量是闭包的,可以保证自己的状态而不被回收,闭包这个就不用我多解释了,大家都懂得。
以上
其实清楚了闭包的特性就会明白为什么了。
当一个函数返回它内部定义的一个函数时,就产生了一个闭包,
闭包包括了被返回的函数以及这个函数的定义环境
。
题主例子中的
匿名函数
自执行后,
ProxySingletonCreateDiv
和
匿名函数
内的局部变量
instance
就是一个闭包,相当于
instance
并没有随着
匿名函数
自执行后而释放。
在还没有调用
ProxySingletonCreateDiv
时,变量
instance
为
undefined
。
当第一次调用
ProxySingletonCreateDiv
时,由于
if
语句为
true
,变量
instance
被赋值为了
CreateDiv
的一个对象。
当第二次调用
ProxySingletonCreateDiv
时,由于
if
语句为
false
,变量
instance
不会再被赋值,还是第一次调用后的值。