代码之家  ›  专栏  ›  技术社区  ›  user123444555621

在javascript中从任何给定类创建单例

  •  0
  • user123444555621  · 技术社区  · 16 年前

    我编写了以下函数,允许从给定类创建单例类:

    function SingletonFrom(Constructor) {
        return function() {
            var self = arguments.callee;
            if (self._instance === undefined) {
                switch (arguments.length) { // this is ugly
                    case  0: self._instance = new Constructor(); break;
                    case  1: self._instance = new Constructor(arguments[0]); break;
                    case  2: self._instance = new Constructor(arguments[0], arguments[1]); break;
                    // [...]
                    case 10: // ...
                    default: throw new Error('Error in Singleton: Constructor may take at most 10 arguments'); break;
                }
            }
            return self._instance;
        }
    }
    

    例子:

    var Array_Singleton = new SingletonFrom(Array);
    var x = new Array_Singleton(1,2,3);   // [1,2,3]
    var y = new Array_Singleton(0,0,0,0); // [1,2,3]
    alert(x === y); // true
    

    它工作得很好,但是我对它不太满意 switch 陈述问题是将数量可变的参数传递给使用“”调用的构造函数 new “关键字是不可能的。因此,我的构造函数的参数不能超过10个。例如,这将失败:

    new Array_Singleton(1,2,3,4,5,6,7,8,9,10,11);
    

    2 回复  |  直到 16 年前
        1
  •  1
  •   kangax    16 年前

    恼人的限制 无法使用数组作为参数列表调用构造函数。通常用什么来完成 Function.prototype.apply 将函数作为函数调用时(例如。 foo(...) ),当函数被称为构造函数时,无法轻松应用于该函数(例如。 new foo(...)

    我猜这正是你求助于 switch 那里

    function foo(a,b) {
      return a+b;
    }
    foo.apply(null, [1,2]); // 3
    

    但使用构造函数并不容易:

    function Person(fname, lname) {
      this.fname = fname;
      this.lname = lname;
    }
    Person.prototype.speak = function() {
      return 'Hi. My name is: ' + this.fname + ' ' + this.lname;
    }
    
    new Person.apply(null, ['John', 'Appleseed']); // doesn't work!
    

    为了解决这个问题,您可以创建一个简单的助手,它实际上 new ,只有这一次 apply . 算法很简单:

    1. 使用 应用 在这个新创建的对象的上下文中调用构造函数,用 应用

    它看起来像这样:

    function newApply(ctr, array) {
      function F(){}
      F.prototype = ctr.prototype;
      var obj = new F();
      ctr.apply(obj, array);
      return obj;
    }
    newApply(Person, ['John', 'Appleseed']); // returns new object
    

    或者,您可以避免 F 节省性能和内存消耗 :

    var newApply = (function(){
      function F(){}
      return function(ctr, array) {
        F.prototype = ctr.prototype;
        var obj = new F();
        ctr.apply(obj, array);
        return obj;
      }
    })();
    
        2
  •  0
  •   Justin Niessner    16 年前

    大量的测试 .

    new . 一旦有了字符串,就可以调用 eval()

    这将为您提供一种处理任意数量的动态参数的方法。