用JavaScript实现单例模式的最简单/最干净的方法是什么?
当前回答
您可以在每次新的执行中返回相同的实例-
function Singleton() {
// lazy
if (Singleton.prototype.myInstance == undefined) {
Singleton.prototype.myInstance = { description: "I am the instance"};
}
return Singleton.prototype.myInstance;
}
a = new Singleton();
b = new Singleton();
console.log(a); // { description: "I am the instance"};
console.log(b); // { description: "I am the instance"};
console.log(a==b); // true
其他回答
你没说"在浏览器里"否则,你可以使用Node.js模块。这些对于每个require调用都是相同的。基本的例子:
foo.js的内容: Const circle = require('./circle.js'); console.log('半径为4的圆的面积为${circle.area(4)} '); circle.js的内容: const PI = Math.PI; 出口。area = (r) => PI * r * r; 出口。周长= (r) => 2 * PI * r;
注意,您不能访问圆。PI,因为它没有导出。
虽然这在浏览器中不起作用,但它简单而干净。
我喜欢将单例模式和模块模式结合起来使用,并将初始化时分支与Global NS检查结合起来使用,并将它们包装在一个闭包中。
在初始化单例后环境不会改变的情况下,使用立即调用的object-literal来返回一个充满实用程序的模块,该模块将持续一段时间。
我没有传递任何依赖项,只是在它们自己的小世界中调用单例对象——唯一的目标是:为事件绑定/解绑定创建一个实用程序模块(设备方向/方向变化也可以在这种情况下工作)。
window.onload = ( function( _w ) {
console.log.apply( console, ['it', 'is', 'on'] );
( {
globalNS : function() {
var nameSpaces = ["utils", "eventUtils"],
nsLength = nameSpaces.length,
possibleNS = null;
outerLoop:
for ( var i = 0; i < nsLength; i++ ) {
if ( !window[nameSpaces[i]] ) {
window[nameSpaces[i]] = this.utils;
break outerLoop;
};
};
},
utils : {
addListener : null,
removeListener : null
},
listenerTypes : {
addEvent : function( el, type, fn ) {
el.addEventListener( type, fn, false );
},
removeEvent : function( el, type, fn ) {
el.removeEventListener( type, fn, false );
},
attachEvent : function( el, type, fn ) {
el.attachEvent( 'on'+type, fn );
},
detatchEvent : function( el, type, fn ) {
el.detachEvent( 'on'+type, fn );
}
},
buildUtils : function() {
if ( typeof window.addEventListener === 'function' ) {
this.utils.addListener = this.listenerTypes.addEvent;
this.utils.removeListener = this.listenerTypes.removeEvent;
} else {
this.utils.attachEvent = this.listenerTypes.attachEvent;
this.utils.removeListener = this.listenerTypes.detatchEvent;
};
this.globalNS();
},
init : function() {
this.buildUtils();
}
} ).init();
} ( window ) );
模块模式:“更具可读性的风格”。您可以很容易地看到哪些方法是公共的,哪些是私有的
var module = (function(_name){
/* Local Methods & Values */
var _local = {
name : _name,
flags : {
init : false
}
}
function init(){
_local.flags.init = true;
}
function imaprivatemethod(){
alert("Hi, I'm a private method");
}
/* Public Methods & variables */
var $r = {}; // This object will hold all public methods.
$r.methdo1 = function(){
console.log("method1 calls it");
}
$r.method2 = function(){
imaprivatemethod(); // Calling private method
}
$r.init = function(){
inti(); // Making 'init' public in case you want to init manually and not automatically
}
init(); // Automatically calling the init method
return $r; // Returning all public methods
})("module");
现在你可以使用公共方法,比如
module.method2 ();// ->我正在调用一个私有方法超过一个公共方法警报(“嗨,我是一个私有方法”)
http://jsfiddle.net/ncubica/xMwS9/
所以公平地说,最简单的答案通常是最好的。一个对象字面值总是一个实例。没有什么理由去做更复杂的事情,除了按需分配内存。
话虽如此,这里是一个使用ES6的经典单例实现。
实例“field”是“private”。这实际上意味着我们将实例隐藏为构造函数的属性。某个不是构造函数的地方。原型,它将通过原型继承对实例可用。 构造函数是“private”。当调用者不是静态getInstance方法时,我们实际上只是抛出一个错误。
同样值得注意。理解这个关键词在不同语境下的含义是很重要的。
在构造函数中,this指向创建的实例。
在静态getInstance方法中,this指向dot的左边,宇宙构造函数,它是一个对象,像JS中的大多数东西一样,可以保存属性。
class Universe { constructor() { if (!((new Error).stack.indexOf("getInstance") > -1)) { throw new Error("Constructor is private. Use static method getInstance."); } this.constructor.instance = this; this.size = 1; } static getInstance() { if (this.instance) { return this.instance; } return new this; } expand() { this.size *= 2; return this.size; } } console.log(Universe.getInstance()) console.log(Universe.getInstance().expand()) console.log(Universe.getInstance()) console.log(new Universe())
单例模式:
确保一个类只有一个实例,并提供对它的全局访问点。
单例模式将特定对象的实例数量限制为一个。这个单一实例称为单例。
定义返回唯一实例的getInstance()。 负责创建和管理实例对象。
单例对象被实现为一个即时匿名函数。函数立即执行,将它括在括号中,然后再加上两个括号。它被称为匿名,因为它没有名字。
示例程序
var Singleton = (function () { var instance; function createInstance() { var object = new Object("I am the instance"); return object; } return { getInstance: function () { if (!instance) { instance = createInstance(); } return instance; } }; })(); function run() { var instance1 = Singleton.getInstance(); var instance2 = Singleton.getInstance(); alert("Same instance? " + (instance1 === instance2)); } run()
推荐文章
- 给一个数字加上st, nd, rd和th(序数)后缀
- 函数可以作为参数传递吗?
- 如何以编程方式触发引导模式?
- setTimeout带引号和不带括号的区别
- 在JS的Chrome CPU配置文件中,'self'和'total'之间的差异
- 用javascript检查输入字符串中是否包含数字
- 如何使用JavaScript分割逗号分隔字符串?
- 在Javascript中~~(“双波浪号”)做什么?
- 谷歌chrome扩展::console.log()从后台页面?
- 未捕获的SyntaxError:
- [].slice的解释。调用javascript?
- jQuery日期/时间选择器
- 我如何预填充一个jQuery Datepicker文本框与今天的日期?
- 数组的indexOf函数和findIndex函数的区别
- jQuery添加必要的输入字段