JavaScript使用模块模式创建类

时间:2013-09-26 15:37:55

标签: javascript module-pattern

我使用模块模式创建一个类cuz我需要一些私有成员和函数。问题是我无法为一个模块创建多个实例。如果我创建一个新实例,它将替换我之前创建的所有实例。

这是代码。

var MyObj = (function() {
    var myVar;
    function MyObj(arg) {
       myVar = arg;
    }
    MyObj.prototype.print = function() {
       console.log(myVar);
    };
    return MyObj;
})();
var instance1 = new MyObj('instance1');
var instance2 = new MyObj('instance2');
instance1.print(); // instance2
instance2.print(); // instance2

这是我的问题: 1.这是否意味着如果我想使用这种模式,我不能为一个类创建多个实例? 2.如果我不能使用这种模式,那么其他方面是否可以在课堂上私有?

5 个答案:

答案 0 :(得分:3)

您至少有四个选择:

  1. 解决方案grape_mao outlined,即Crockford's private pattern。它的问题是每个实例都获得了自己的 getMyVar函数,它们无法共享它们。这是目前在JavaScript中获取真正私有属性的唯一方法。

  2. 解决方案Tibos outlined,其中myVar不再是私有的,但所有原型函数都可以访问它,你没有为每个实例提供新的访问函数。 / p>

  3. 与#2相同的解决方案,在属性名称前面加上_。纯粹作为惯例,名称以_开头的属性应该禁止对象外部的代码。它不是远程私人的,但它很便宜。我曾经完全嘲笑这种方法,但是有人向我指出,现在大多数现代语言都有反射,私人成员即使在Java和C#等也不是私密的。 : - )

  4. 使用ES6 will use with private Name objects模式,用随机字符串替换私有Name对象(因为它们不存在!)。您的代码不担心属性的实际名称,其他代码无法合理地猜测它。仍然只是伪私人,但比#2或#3更私密;不如#1多。我概述了它的工作原理in this article。基本上它看起来像这样:

    var MyObj = (function() {
        var myVarName = new Name();
        function MyObj(arg) {
           this[myVarName] = arg;
        }
        MyObj.prototype.print = function() {
           console.log(this[myVarName]);
        };
        return MyObj;
    })();
    var instance1 = new MyObj('instance1');
    var instance2 = new MyObj('instance2');
    instance1.print(); // instance2
    instance2.print(); // instance2
    

    ...其中Name看起来像这样:

    var Name = function() {
        var used = {};
    
        function Name() {
            var length, str;
    
            do {
                length = 5 + Math.floor(Math.random() * 10);
                str = "_";
                while (length--) {
                    str += String.fromCharCode(32 + Math.floor(95 * Math.random()));
                }
            }
            while (used[str]);
            used[str] = true;
            return new String(str); // Since this is called via `new`, we have to return an object to override the default
        }
    
        return Name;
    }();
    

    the article中的详细信息。

答案 1 :(得分:2)

您有MyObj类的多个实例,但是您使用myVar作为静态变量,因此它在实例之间共享。

此代码应该可以正常运行:

var MyObj = (function() {
    function MyObj(arg) {
       this.myVar = arg;
    }
    MyObj.prototype.print = function() {
       console.log(this.myVar);
    };
    return MyObj;
})();
var instance1 = new MyObj('instance1');
var instance2 = new MyObj('instance2');
instance1.print(); // instance1
instance2.print(); // instance2

演示:http://jsbin.com/EPirAki/1/edit

看一下这篇博文(简称T.J.Crowder - 见评论),它解释了如何使用随机来获得近乎私有的变量:http://blog.niftysnippets.org/2013/05/private-properties-in-es6-and-es3-and.html

答案 2 :(得分:1)

您需要一个可以访问该变量的权限函数。

var MyObj = (function() {
function MyObj(arg) {
    this.getMyVar = function(){
         return arg;   
    };
}
MyObj.prototype.print = function() {
    console.log(this.getMyVar());
};
    return MyObj;
})();
var instance1 = new MyObj('instance1');
var instance2 = new MyObj('instance2');
instance1.print(); // instance2
instance2.print(); // instance2

答案 3 :(得分:0)

原型函数不能直接访问私有变量。

var MyObj = (function() {
  var abc = "shared by all MyObj";   // this variable is shared through all  MyObj instances created and doesn't belong to MyObj
  function MyObj(arg) {
    var privateVar = arg;
    this.getPrivateVar = function(){ return privateVar; }
    this.myVar = arg;
  }
  MyObj.prototype.print = function() {
    //console.log(privateVar);  // cannot access variable
    console.log(this.getPrivateVar());  // using a getter function you can access that   private variable and limit its mutation
    console.log(this.myVar);
  };
  return MyObj;
})();
var instance1 = new MyObj('instance1');
var instance2 = new MyObj('instance2');
instance1.print(); // instance2
instance2.print(); // instance2

答案 4 :(得分:0)

我对原型设计知之甚少,但我认为使用模块模式会产生更简单的东西,比如:

var MyObj = function(arg){
    var myVar = arg;

    var pub = {
        print: function(){
            console.log(myVar);
        }
    }

    return pub;
};

var instance1 = MyObj('instance1');
var instance2 = MyObj('instance2');
instance1.print(); // instance1
instance2.print(); // instance2

同意,你没有这个'等级'。但对我来说,模块模式的重点是封装没有类似的麻烦。