用JavaScript实现单例模式的最简单/最干净的方法是什么?
当前回答
你可以用下面这个例子中的TypeScript装饰器来做:
class YourClass {
@Singleton static singleton() {}
}
function Singleton(target, name, descriptor) {
var instance;
descriptor.value = () => {
if(!instance) instance = new target;
return instance;
};
}
然后你像这样使用你的单例:
var myInstance = YourClass.singleton();
在撰写本文时,JavaScript引擎中还没有装饰器。你需要确保你的JavaScript运行时实际上启用了装饰器,或者使用像Babel和TypeScript这样的编译器。
还要注意的是,单例实例是“惰性”创建的,也就是说,只有当你第一次使用它时才会创建它。
其他回答
最明确的答案应该是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; } }; })();
剥猫皮的方法不止一种:)根据你的口味或特定需求,你可以应用任何一种建议的解决方案。我个人倾向于Christian C. Salvadó的第一个解决方案(当你不需要隐私的时候)。
因为这个问题是关于最简单和最干净的,所以这个问题是赢家。甚至:
var myInstance = {}; // Done!
这(引用自我的博客)……
var SingletonClass = new function() {
this.myFunction() {
// Do stuff
}
this.instance = 1;
}
没有太大的意义(我的博客例子也没有),因为它不需要任何私有变量,所以它几乎与:
var SingletonClass = {
myFunction: function () {
// Do stuff
},
instance: 1
}
我认为最简单的方法是声明一个简单的对象文字:
var myInstance = {
method1: function () {
// ...
},
method2: function () {
// ...
}
};
如果你想在你的单例实例上有私有成员,你可以这样做:
var myInstance = (function() {
var privateVar = '';
function privateMethod () {
// ...
}
return { // public interface
publicMethod1: function () {
// All private members are accessible here
},
publicMethod2: function () {
}
};
})();
这被称为模块模式,它基本上允许您通过使用闭包来封装对象上的私有成员。
如果你想阻止对单例对象的修改,你可以使用ES5 object .freeze方法冻结它。
这将使对象不可变,防止对其结构和值进行任何修改。
如果你正在使用ES6,你可以很容易地使用ES模块来表示一个单例,你甚至可以通过在模块范围内声明变量来保持私有状态:
// my-singleton.js
const somePrivateState = []
function privateFn () {
// ...
}
export default {
method1() {
// ...
},
method2() {
// ...
}
}
然后你可以简单地导入单例对象来使用它:
import myInstance from './my-singleton.js'
// ...
我认为我已经找到了用JavaScript编程的最简洁的方法,但您需要一些想象力。我是从《JavaScript: the Good Parts》一书中的一个工作技巧中得到这个想法的。
不用new关键字,你可以这样创建一个类:
function Class()
{
var obj = {}; // Could also be used for inheritance if you don't start with an empty object.
var privateVar;
obj.publicVar;
obj.publicMethod = publicMethod;
function publicMethod(){}
function privateMethod(){}
return obj;
}
你可以这样实例化上面的对象:
var objInst = Class(); // !!! NO NEW KEYWORD
现在有了这个工作方法,你可以创建一个像这样的单例:
ClassSingleton = function()
{
var instance = null;
function Class() // This is the class like the above one
{
var obj = {};
return obj;
}
function getInstance()
{
if( !instance )
instance = Class(); // Again no 'new' keyword;
return instance;
}
return { getInstance : getInstance };
}();
现在可以通过调用来获取实例
var obj = ClassSingleton.getInstance();
我认为这是最简洁的方法,因为完整的“类”甚至无法访问。
单例模式:
确保一个类只有一个实例,并提供对它的全局访问点。
单例模式将特定对象的实例数量限制为一个。这个单一实例称为单例。
定义返回唯一实例的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()
推荐文章
- Babel 6改变了它导出默认值的方式
- 如何配置历史记录?
- ES6模板文字可以在运行时被替换(或重用)吗?
- [Vue警告]:找不到元素
- 可以在setInterval()内部调用clearInterval()吗?
- AngularJS控制器的生命周期是什么?
- 无法读取未定义的属性“msie”- jQuery工具
- 我的蛋蛋怎么不见了?
- JavaScript中的排列?
- JavaScript中有睡眠/暂停/等待功能吗?
- 如何禁用文本选择使用jQuery?
- 如何停止事件冒泡复选框点击
- 如何在PHP中截断字符串最接近于一定数量的字符?
- 向对象数组添加属性
- 如何在Redux应用程序中动态加载代码分割的减速器?