1

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

这是代码。

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. 如果我不能使用这种模式,还有其他方法可以在 Class 中使用 private 吗?

4

5 回答 5

3

你至少有四个选择:

  1. 解决方案grape_mao 概述,这是Crockford 的私有模式。它的问题是每个实例都有自己的 getMyVar功能,他们不能共享它们。这是目前在 JavaScript 中获得真正私有属性的唯一方法。

  2. Tibos 概述的解决方案,其中myVar不再是私有的,但所有原型函数都可以访问它,您没有每个实例都有新的访问器函数。

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

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

    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;
    }();
    

    文章中的详细信息。

于 2013-09-26T15:53:47.000 回答
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

看看这篇博文(TJ Crowder 的屈膝 - 见评论),它解释了如何使用随机来获取接近私有的变量:http: //blog.niftysnippets.org/2013/05/private-properties-in- es6-and-es3-and.html

于 2013-09-26T15:40:53.433 回答
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
于 2013-09-26T15:48:23.000 回答
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
于 2013-09-26T15:50:08.310 回答
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

同意,你没有这个“类”。但对我来说,模块模式的全部意义在于封装没有类的麻烦。

于 2013-10-14T11:30:21.753 回答