用JavaScript实现单例模式的最简单/最干净的方法是什么?
当前回答
我不确定我是否同意用模块模式来代替单例模式。我经常看到单例对象在完全没有必要的地方被使用和滥用,我确信模块模式填补了程序员使用单例对象的许多空白。然而,模块模式不是单例的。
模块模式:
var foo = (function () {
"use strict";
function aPrivateFunction() {}
return { aPublicFunction: function () {...}, ... };
}());
在模块模式中初始化的所有内容都在声明Foo时发生。此外,模块模式可用于初始化构造函数,然后可以多次实例化构造函数。虽然模块模式是许多工作的正确工具,但它并不等同于单例模式。
单例模式:
简式
var Foo = function () {
"use strict";
if (Foo._instance) {
// This allows the constructor to be called multiple times
// and refer to the same instance. Another option is to
// throw an error.
return Foo._instance;
}
Foo._instance = this;
// Foo initialization code
};
Foo.getInstance = function () {
"use strict";
return Foo._instance || new Foo();
}
长格式,使用模块模式
var Foo = (function () {
"use strict";
var instance; //prevent modification of "instance" variable
function Singleton() {
if (instance) {
return instance;
}
instance = this;
//Singleton initialization code
}
// Instance accessor
Singleton.getInstance = function () {
return instance || new Singleton();
}
return Singleton;
}());
在我提供的两个版本的单例模式中,构造函数本身都可以用作访问器:
var a,
b;
a = new Foo(); // Constructor initialization happens here
b = new Foo();
console.log(a === b); //true
如果你不习惯这样使用构造函数,你可以在If (instance)语句中抛出一个错误,并坚持使用长形式:
var a,
b;
a = Foo.getInstance(); // Constructor initialization happens here
b = Foo.getInstance();
console.log(a === b); // true
我还应该提到,单例模式很适合隐式构造函数模式:
function Foo() {
if (Foo._instance) {
return Foo._instance;
}
// If the function wasn't called as a constructor,
// call it as a constructor and return the result
if (!(this instanceof Foo)) {
return new Foo();
}
Foo._instance = this;
}
var f = new Foo(); // Calls Foo as a constructor
-or-
var f = Foo(); // Also calls Foo as a constructor
其他回答
单例模式:
确保一个类只有一个实例,并提供对它的全局访问点。
单例模式将特定对象的实例数量限制为一个。这个单一实例称为单例。
定义返回唯一实例的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()
你可以这样做:
var singleton = new (function() {
var bar = 123
this.foo = function() {
// Whatever
}
})()
下面是一个简单的例子来解释JavaScript中的单例模式。
var Singleton = (function() {
var instance;
var init = function() {
return {
display:function() {
alert("This is a singleton pattern demo");
}
};
};
return {
getInstance:function(){
if(!instance){
alert("Singleton check");
instance = init();
}
return instance;
}
};
})();
// In this call first display alert("Singleton check")
// and then alert("This is a singleton pattern demo");
// It means one object is created
var inst = Singleton.getInstance();
inst.display();
// In this call only display alert("This is a singleton pattern demo")
// it means second time new object is not created,
// it uses the already created object
var inst1 = Singleton.getInstance();
inst1.display();
最明确的答案应该是Addy Osmani所著的《学习JavaScript设计模式》一书。
var mySingleton = (function () { // Instance stores a reference to the singleton var instance; function init() { // Singleton // Private methods and variables function privateMethod(){ console.log( "I am private" ); } var privateVariable = "I'm also private"; var privateRandomNumber = Math.random(); return { // Public methods and variables publicMethod: function () { console.log( "The public can see me!" ); }, publicProperty: "I am also public", getRandomNumber: function() { return privateRandomNumber; } }; }; return { // Get the singleton instance if one exists // or create one if it doesn't getInstance: function () { if ( !instance ) { instance = init(); } return instance; } }; })();
我不确定我是否同意用模块模式来代替单例模式。我经常看到单例对象在完全没有必要的地方被使用和滥用,我确信模块模式填补了程序员使用单例对象的许多空白。然而,模块模式不是单例的。
模块模式:
var foo = (function () {
"use strict";
function aPrivateFunction() {}
return { aPublicFunction: function () {...}, ... };
}());
在模块模式中初始化的所有内容都在声明Foo时发生。此外,模块模式可用于初始化构造函数,然后可以多次实例化构造函数。虽然模块模式是许多工作的正确工具,但它并不等同于单例模式。
单例模式:
简式
var Foo = function () {
"use strict";
if (Foo._instance) {
// This allows the constructor to be called multiple times
// and refer to the same instance. Another option is to
// throw an error.
return Foo._instance;
}
Foo._instance = this;
// Foo initialization code
};
Foo.getInstance = function () {
"use strict";
return Foo._instance || new Foo();
}
长格式,使用模块模式
var Foo = (function () {
"use strict";
var instance; //prevent modification of "instance" variable
function Singleton() {
if (instance) {
return instance;
}
instance = this;
//Singleton initialization code
}
// Instance accessor
Singleton.getInstance = function () {
return instance || new Singleton();
}
return Singleton;
}());
在我提供的两个版本的单例模式中,构造函数本身都可以用作访问器:
var a,
b;
a = new Foo(); // Constructor initialization happens here
b = new Foo();
console.log(a === b); //true
如果你不习惯这样使用构造函数,你可以在If (instance)语句中抛出一个错误,并坚持使用长形式:
var a,
b;
a = Foo.getInstance(); // Constructor initialization happens here
b = Foo.getInstance();
console.log(a === b); // true
我还应该提到,单例模式很适合隐式构造函数模式:
function Foo() {
if (Foo._instance) {
return Foo._instance;
}
// If the function wasn't called as a constructor,
// call it as a constructor and return the result
if (!(this instanceof Foo)) {
return new Foo();
}
Foo._instance = this;
}
var f = new Foo(); // Calls Foo as a constructor
-or-
var f = Foo(); // Also calls Foo as a constructor
推荐文章
- 如何让一个按钮将我的页面重定向到另一个页面?
- 什么时候我们应该使用观察者和可观察对象?
- 如何让元素被点击(对于整个文档)?
- 我如何检查如果一个变量是JavaScript字符串?
- 如何检测如果多个键被按下一次使用JavaScript?
- 如何通过history. pushstate获得历史变化的通知?
- 使用jQuery改变输入字段的类型
- 在JavaScript中,什么相当于Java的Thread.sleep() ?
- 使用jQuery以像素为整数填充或边距值
- 检查是否选择了jQuery选项,如果没有选择默认值
- Next.js React应用中没有定义Window
- 如何重置笑话模拟函数调用计数之前,每次测试
- 如何强制一个功能React组件渲染?
- 在javascript中从平面数组构建树数组
- 将Dropzone.js与其他字段集成到现有的HTML表单中