用JavaScript实现单例模式的最简单/最干净的方法是什么?
当前回答
这应该可以工作:
function Klass() {
var instance = this;
Klass = function () { 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
class Singelton {
static #instance;
#testValue;
constructor() {
if (Singelton.#instance instanceof Singelton) {
return Singelton.#instance;
}
Singelton.#instance = this;
return Singelton.#instance;
}
get testValue() {
return this.#testValue;
}
set testValue(value) {
this.#testValue = value;
}
}
测试:
let x = new Singelton();
x.testValue = 123;
let y = new Singelton();
console.log({isSingelton: x === y, testValueFromY: y.testValue});
单例模式:
确保一个类只有一个实例,并提供对它的全局访问点。
单例模式将特定对象的实例数量限制为一个。这个单一实例称为单例。
定义返回唯一实例的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()
这也是一个单例:
function Singleton() {
var i = 0;
var self = this;
this.doStuff = function () {
i = i + 1;
console.log('do stuff', i);
};
Singleton = function () { return self };
return this;
}
s = Singleton();
s.doStuff();
这个知识是基于我正在学习Java,虽然Java和Javascript是不同的,但单例的概念和Java如何做到这一点是一样的。在我看来,JS的类样式本身是干净的,而不是var初始化。
class Singleton {
// use hashtag which entails that the variable can only be accessed from self scope
static #instance = null;
static getInstance() {
if (this.#instance === null) this.#instance = new Singleton();
return this.#instance;
}
// some class property
hello = 'world';
// or initialize the variable in the constructor, depend on your preference
constructor() {
// this.hello = 'world';
}
/* you can also add parameters on the constructor & getInstance
* e.g.
* static getInstance(param1, param2) {...new Singleton(param1, param2)}
* constructor(param1, param2) {...}
*/
}
// this is the same code for java and normal way for singleton for class
// just use static so you can get instance
// testing the singleton
var s1,s2;
s1 = Singleton.getInstance();
s2 = Singleton.getInstance();
// you cannot access the property, immediately
if (Singleton.hello === undefined) console.log('getInstance so you can access this');
console.log(s1.hello);
// result: "world"
console.log(s2.hello);
// result: "world"
// set the value of Singleton object
s2.hello = "hi";
console.log(s1.hello);
// result: "hi"
console.log(s2.hello);
// result: "hi"
// this is just an evidence which means that they are the same even in property level
if (s1 === s2) console.log("S1 & S2 is the same object");
// result: "S1 & S2 is the same object"
// don't use something like `var s1 = new Singleton();`
// this will defeat your purpose of just (1 object), one instance of class
推荐文章
- Babel 6改变了它导出默认值的方式
- 如何配置历史记录?
- ES6模板文字可以在运行时被替换(或重用)吗?
- [Vue警告]:找不到元素
- 可以在setInterval()内部调用clearInterval()吗?
- AngularJS控制器的生命周期是什么?
- 无法读取未定义的属性“msie”- jQuery工具
- 我的蛋蛋怎么不见了?
- JavaScript中的排列?
- JavaScript中有睡眠/暂停/等待功能吗?
- 如何禁用文本选择使用jQuery?
- 如何停止事件冒泡复选框点击
- 如何在PHP中截断字符串最接近于一定数量的字符?
- 向对象数组添加属性
- 如何在Redux应用程序中动态加载代码分割的减速器?