在JavaScript中实现单例的最简单/最干净的方法

在JavaScript中实现单例的最简单/最干净的方法,javascript,function,design-patterns,singleton,Javascript,Function,Design Patterns,Singleton,在JavaScript中实现的最简单/最干净的方法是什么?我认为最简单的方法是声明一个简单的对象文字: var myInstance = { method1: function () { // ... }, method2: function () { // ... } }; 如果您想在singleton实例上使用私有成员,可以执行以下操作: var myInstance = (function() { var privateVar = ''; fun

在JavaScript中实现的最简单/最干净的方法是什么?

我认为最简单的方法是声明一个简单的对象文字:

var myInstance = {
  method1: function () {
    // ...
  },
  method2: function () {
    // ...
  }
};
如果您想在singleton实例上使用私有成员,可以执行以下操作:

var myInstance = (function() {
  var privateVar = '';

  function privateMethod () {
    // ...
  }

  return { // public interface
    publicMethod1: function () {
      // All private members are accessible here
    },
    publicMethod2: function () {
    }
  };
})();
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;
}
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 myInstance = YourClass.singleton();
这被称为,它基本上允许您通过使用来封装对象上的私有成员

如果要防止修改singleton对象,可以使用ES5方法冻结它

这将使对象不可变,防止对其结构和值进行任何修改

如果您使用的是ES6,那么您可以非常轻松地使用ES模块来表示一个单例,甚至可以通过在模块范围内声明变量来保持私有状态:

然后,只需导入singleton对象即可使用它:

import myInstance from './my-singleton.js'
// ...

我认为最简单的方法是声明一个简单的对象文字:

var myInstance = {
  method1: function () {
    // ...
  },
  method2: function () {
    // ...
  }
};
如果您想在singleton实例上使用私有成员,可以执行以下操作:

var myInstance = (function() {
  var privateVar = '';

  function privateMethod () {
    // ...
  }

  return { // public interface
    publicMethod1: function () {
      // All private members are accessible here
    },
    publicMethod2: function () {
    }
  };
})();
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;
}
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 myInstance = YourClass.singleton();
这被称为,它基本上允许您通过使用来封装对象上的私有成员

如果要防止修改singleton对象,可以使用ES5方法冻结它

这将使对象不可变,防止对其结构和值进行任何修改

如果您使用的是ES6,那么您可以非常轻松地使用ES模块来表示一个单例,甚至可以通过在模块范围内声明变量来保持私有状态:

然后,只需导入singleton对象即可使用它:

import myInstance from './my-singleton.js'
// ...

我认为最干净的方法是:

var SingletonFactory = (function(){
    function SingletonClass() {
        //do stuff
    }
    var instance;
    return {
        getInstance: function(){
            if (instance == null) {
                instance = new SingletonClass();
                // Hide the constructor so the returned object can't be new'd...
                instance.constructor = null;
            }
            return instance;
        }
   };
})();
之后,您可以根据需要调用该函数

var test = SingletonFactory.getInstance();

我认为最干净的方法是:

var SingletonFactory = (function(){
    function SingletonClass() {
        //do stuff
    }
    var instance;
    return {
        getInstance: function(){
            if (instance == null) {
                instance = new SingletonClass();
                // Hide the constructor so the returned object can't be new'd...
                instance.constructor = null;
            }
            return instance;
        }
   };
})();
之后,您可以根据需要调用该函数

var test = SingletonFactory.getInstance();

给猫剥皮的方法不止一种:)根据你的口味或具体需要,你可以采用任何建议的解决方案。只要有可能(当你不需要隐私时),我个人都会选择

既然问题是关于最简单和最干净的,那就是赢家。甚至:

var myInstance = {}; // Done!
这(引用我的博客)

没有多大意义(我的博客示例也没有),因为它不需要任何私有变量,所以它与:

var SingletonClass = {
    myFunction: function () {
        // Do stuff
    },
    instance: 1
}

给猫剥皮的方法不止一种:)根据你的口味或具体需要,你可以采用任何建议的解决方案。只要有可能(当你不需要隐私时),我个人都会选择

既然问题是关于最简单和最干净的,那就是赢家。甚至:

var myInstance = {}; // Done!
这(引用我的博客)

没有多大意义(我的博客示例也没有),因为它不需要任何私有变量,所以它与:

var SingletonClass = {
    myFunction: function () {
        // Do stuff
    },
    instance: 1
}

我不赞成我的回答,明白吗

通常模块模式(请参阅)不是单例模式就足够了。但是,singleton的一个特性是它的初始化延迟到需要对象时。模块模式缺少此功能

我的建议(咖啡脚本):

在JavaScript中编译为:

window.singleton = function(initializer) {
    var instance;
    instance = void 0;
    return function() {
        if (instance !== void 0) {
            return instance;
        }
        return instance = initializer();
    };
};
然后我可以做以下几点:

window.iAmSingleton = singleton(function() {
    /* This function should create and initialize singleton. */
    alert("creating");
    return {property1: 'value1', property2: 'value2'};
});


alert(window.iAmSingleton().property2); // "creating" will pop up; then "value2" will pop up
alert(window.iAmSingleton().property2); // "value2" will pop up but "creating" will not
window.iAmSingleton().property2 = 'new value';
alert(window.iAmSingleton().property2); // "new value" will pop up
var ClassName;

(function() {
    var instance;
    ClassName = function ClassName() {
        // If the private instance variable is already initialized, return a reference
        if(instance) {
            return instance;
        }
        // If the instance is not created, save a pointer of the original reference
        // to the private instance variable.
        instance = this;

        // All constructor initialization will be here
        // i.e.:
        this.someProperty = 0;
        this.someMethod = function() {
            // Some action here
        };
    };
}());

我不赞成我的回答,明白吗

通常模块模式(请参阅)不是单例模式就足够了。但是,singleton的一个特性是它的初始化延迟到需要对象时。模块模式缺少此功能

我的建议(咖啡脚本):

在JavaScript中编译为:

window.singleton = function(initializer) {
    var instance;
    instance = void 0;
    return function() {
        if (instance !== void 0) {
            return instance;
        }
        return instance = initializer();
    };
};
然后我可以做以下几点:

window.iAmSingleton = singleton(function() {
    /* This function should create and initialize singleton. */
    alert("creating");
    return {property1: 'value1', property2: 'value2'};
});


alert(window.iAmSingleton().property2); // "creating" will pop up; then "value2" will pop up
alert(window.iAmSingleton().property2); // "value2" will pop up but "creating" will not
window.iAmSingleton().property2 = 'new value';
alert(window.iAmSingleton().property2); // "new value" will pop up
var ClassName;

(function() {
    var instance;
    ClassName = function ClassName() {
        // If the private instance variable is already initialized, return a reference
        if(instance) {
            return instance;
        }
        // If the instance is not created, save a pointer of the original reference
        // to the private instance variable.
        instance = this;

        // All constructor initialization will be here
        // i.e.:
        this.someProperty = 0;
        this.someMethod = function() {
            // Some action here
        };
    };
}());

我不确定我是否同意将模块模式用作单例模式的替代品。我经常看到在完全不必要的地方使用和滥用单例,我确信模块模式填补了程序员使用单例的许多空白。但是,模块模式不是单例模式

模块模式: 当声明
Foo
时,模块模式中初始化的所有内容都会发生。此外,模块模式可用于初始化构造函数,然后可以多次实例化构造函数。虽然模块模式是许多作业的正确工具,但它并不等同于单例

单件模式: 缩略形式 长格式,使用模块模式 在我提供的两个单例模式版本中,构造函数本身都可以用作访问器:

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

我还应该提到,singleton模式与隐式构造函数模式非常匹配:

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

我不确定我是否同意将模块模式用作单例模式的替代品。我经常看到在完全不必要的地方使用和滥用单例,我确信模块模式填补了程序员使用单例的许多空白。但是,模块模式不是单例模式

模块模式: 当声明
Foo
时,模块模式中初始化的所有内容都会发生。此外,模块模式可用于初始化构造函数,然后可以多次实例化构造函数。虽然模块模式是许多作业的正确工具,但它并不等同于单例

单件模式: 缩略形式 长格式,使用模块模式 在我提供的两个单例模式版本中,构造函数本身都可以用作访问器:

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

我还应该提到,singleton模式与隐式构造函数模式非常匹配:

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

我需要几个单身汉:

  • 惰性初始化<
    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();
    
    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();
    
    var A = function(arg1){
      this.arg1 = arg1
    };
    
    var X = function(){
      var instance = {};
      return function(){ return instance; }
    }();
    
    var x1 = new X();
    var x2 = new X();
    console.log(x1 === x2)
    
    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();
    
    export default class Singleton {
    
      static instance;
    
      constructor(){
        if(instance){
          return instance;
        }
    
        this.state = "duke";
        this.instance = this;
      }
    
    }
    
    class Singleton {
      constructor () {
        if (!Singleton.instance) {
          Singleton.instance = this
        }
        // Initialize object
        return Singleton.instance
      }
      // Properties & Methods
    }
    
    const instance = new Singleton()
    Object.freeze(instance)
    
    export default instance
    
    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();
    
    class Foo {
      constructor(msg) {
    
        if (Foo.singleton) {
          return Foo.singleton;
        }
    
        this.msg = msg;
        Foo.singleton = this;
        return Foo.singleton;
      }
    }
    
    const f = new Foo('blah');
    const d = new Foo('nope');
    console.log(f); // => Foo { msg: 'blah' }
    console.log(d); // => Foo { msg: 'blah' }
    
    console.log(Singleton.getInstance().field1);
    console.log(Singleton.getInstance().field2);
    
    DefaultField1
    DefaultField2
    
    function Once() {
        return this.constructor.instance || (this.constructor.instance = this);
    }
    
    function Application(name) {
        let app = Once.call(this);
    
        app.name = name;
    
        return app;
    }
    
    class Once {
        constructor() {
            return this.constructor.instance || (this.constructor.instance = this);
        }
    }
    
    class Application extends Once {
        constructor(name) {
            super();
    
            this.name = name;
        }
    }
    
    console.log(new Once() === new Once());
    
    let app1 = new Application('Foobar');
    let app2 = new Application('Barfoo');
    
    console.log(app1 === app2);
    console.log(app1.name); // Barfoo
    
    const singleton = new class {
        name = "foo"
        constructor() {
            console.log(`Singleton ${this.name} constructed`)
        }
    }
    
    class Singleton {
      constructor(name, age) {
        this.name = name;
        this.age = age;
        if(this.constructor.instance)
          return this.constructor.instance;
        this.constructor.instance = this;
      }
    }
    let x = new Singleton('s', 1);
    let y = new Singleton('k', 2);
    
    console.log(x.name, x.age, y.name, y.age) // s 1 s 1
    
    function AnotherSingleton (name,age) {
      this.name = name;
      this.age = age;
      if(this.constructor.instance)
        return this.constructor.instance;
      this.constructor.instance = this;
    }
    
    let a = new AnotherSingleton('s', 1);
    let b = new AnotherSingleton('k', 2);
    
    console.log(a.name, a.age, b.name, b.age) // s 1 s 1