window.onload = function() {
var Createp=function(html){
this.html=html;
this.init();
}
Createp.prototype.init=function(){
var p=document.createElement("p");
p.innerHTML=this.html;
document.body.appendChild(p);
}
//这个代理类为什么要用匿名函数自执行,写成普通函数为什么却没用?
var ProxySingletonCreatep=(function(){
var instance;
return function(html){
if(!instance){
instance=new Createp(html);
}
return instance;
}
})();
var a=new ProxySingletonCreatep("sven1");
var b=new ProxySingletonCreatep("sven2");
alert(a===b);
}
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号
这个匿名函数形成了一个闭包,单例对象instance会保存在这个闭包中,防止它不会被回收掉
其实清楚了闭包的特性就会明白为什么了。
当一个函数返回它内部定义的一个函数时,就产生了一个闭包,闭包包括了被返回的函数以及这个函数的定义环境。
题主例子中的
匿名函数
自执行后,ProxySingletonCreatep
和匿名函数
内的局部变量instance
就是一个闭包,相当于instance
并没有随着匿名函数
自执行后而释放。在还没有调用
ProxySingletonCreatep
时,变量instance
为undefined
。当第一次调用
ProxySingletonCreatep
时,由于if
语句为true
,变量instance
被赋值为了Createp
的一个对象。当第二次调用
ProxySingletonCreatep
时,由于if
语句为false
,变量instance
不会再被赋值,还是第一次调用后的值。首先按照LZ说的把自执行去掉改成普通Function的闭包
好,false显然不能满足单例的要求,我们要把代码改成如下才能实现单例
所以这里就有个问题,不使用自执行的方式实现单例就显得不够优雅。再解释区别之前,我们先来说说,用new来初始化一个function和直接调用一个function的区别。来看看下面的例子。
通过上面的例子我们可以看出,使用new关键字初始化的function会返回this对象,而无视return的值,除非return的是一个对象,或者function。 而直接使用Function()方式则直接返回return的值。
好了,讲到这里一些朋友可能已经看出题主的问题关键之所在了,他不是在问闭包的问题,而是new关键字的问题。
当我们使用自执行方式的时候其实 var ProxySingletonCreatep这个变量已经指向了这个自执行匿名函数的return值,也就是另外一个匿名函数
所以,再后面的2次new关键字的使用,其实你new的是上面这个return的匿名函数,由于这个匿名函数本身是return的是一个实例,所以你使用了new关键字也不会影响到它的返回(参见上面的function C()例子 )。因为instance这个变量是闭包的,可以保证自己的状态而不被回收,闭包这个就不用我多解释了,大家都懂得。
以上
代理是单例模式,,作用是只创建一次节点,避免多次创建节点。如
a
b
跳过用户代理,就会创建出两个 p。可以达到同样效果的办法是:
不用代理:把单例直接写在
onload
回调里,但题主之代码其实还有单一职责之意不用单例:
onload
里将其重新设为null
,也能避免重复创建的可能性。如下:返回的函数里面的instance始终指向内部的那个变量==
其实prototype应该也算是单实例