关于Javascript类定义的特定模式的问题

时间:2010-05-25 21:32:53

标签: javascript oop class

最近我看到以下代码在javascript中创建了一个类:

var Model.Foo = function(){
  // private stuff
  var a, b;

  // public properties
  this.attr1 = '';
  this.attr2 = '';

  if(typeof Model.Foo._init === 'undefined'){
    Model.Foo.prototype = {
      func1 : function(){ //...},
      func2 : function(){ //... },
      //other prototype functions
    }
  }
  Model.Foo._init = true;
}

// Instantiate and use the class as follows:
var foo = new Model.Foo(); foo.func1();

我想_init变量用于确保我们不再重新定义原型。此外,我觉得代码更具可读性,因为我将所有内容放在一个功能块中(所以在oop-speak中,所有属性和方法都在一个地方)。 您是否看到上述代码存在任何问题?如果我需要在一个大项目中创建大量的类,使用这种模式的任何陷阱?

4 个答案:

答案 0 :(得分:2)

这是一个奇怪的Javascript模式,我永远不会用它来开发面向对象的JS代码。首先,如果Model.Foo._init === 'undefined'不是字符串trueModel.Foo._init永远不会评估为'undefined';因此,代码

Model.Foo.prototype = {
    func1 : function(){ /* ... */},
    func2 : function(){ /* ... */},
    //other prototype functions
}
除非该条件成立,否则

将不会运行。 (也许作者想要添加typeof,就像typeof Model.Foo._init === 'undefined'一样?我不知道。)

解决您对“确保我们不再定义原型”的担忧,这已经实现了:

Model.Foo = function() {
    // private stuff
    var a, b;

    // public properties
    this.attr1 = '';
    this.attr2 = '';
};

Model.Foo.prototype = {
    func1 : function() { /* ... */},
    func2 : function() { /* ... */}
    //,other prototype functions
};

// Instantiate and use the class as follows:
var foo = new Model.Foo();
foo.func1();

如果你没有使用框架,那就是我推荐的。

基本上,你的问题的答案是:如果你使用这种非标准模式进行开发,那么其他程序员,甚至几个月后你自己也会发现很难扩展和使用它。

答案 1 :(得分:1)

看起来似乎不必要的复杂。您需要遵守纪律,以便在原型扩展的实现中不使用Model.Foo的任何参数或局部变量。奇怪的是覆盖整个.prototype对象,而不仅仅是添加单个成员。为什么不以正常的方式做到这一点?

var Model.Foo = function(){
  // private stuff
  var a, b;

  // public properties
  this.attr1 = '';
  this.attr2 = '';
}

Model.Foo.prototype.func1 = function(){ //...};
Model.Foo.prototype.func2 = function(){ //... };

替代允许每个实例成员变量私有

var Model.Foo = function(){
  // private stuff
  var a, b;

  // public properties
  this.attr1 = '';
  this.attr2 = '';

  this.func1 = function(){ //...};
  this.func2 = function(){ //... };
}

答案 2 :(得分:0)

有些事情可能很麻烦:

  1. Foo.prototype设置为一个简单的对象,使用此模式无法扩展任何内容。
  2. 使用“私人物品”在哪里?每次创建新对象时,都会创建新的私有变量,这些变量似乎只能在Foo.prototype中定义的函数中使用,而这些函数只能运行一次。
  3. 这有点混乱,网上有更好的细节/例子就是这样做。

答案 3 :(得分:0)

以下示例说明了我个人随着时间的推移开发的模式。

它利用作用域来允许私有字段和方法。

有关详细讨论,请查看JavaScript class patterns

Employee = (function(){

  // private static field
  var staticVar;

  // class function a.k.a. constructor
  function cls()
  {
    // private instance field
    var name = "";
    var self = this;

    // public instance field
    this.age = 10;

    // private instance method
    function increment()
    {
        // must use self instead of this
        self.age ++;
    }

    // public instance method  
    this.getName = function(){
        return cls.capitalize(name);
    };

    this.setName = function(name2){
        name = name2;
    };

    this.increment = function(){
        increment();
    };

    this.getAge = function(){
        return this.age;
    };
  }

  // public static field
  cls.staticVar = 0;

  // public static method
  cls.capitalize = function(name){
      return name.substring(0, 1).toUpperCase() + 
          name.substring(1).toLowerCase();
  };

  // private static method
  function createWithName(name)
  {
    var obj = new cls();
    obj.setName(cls.capitalize(name));
    return obj;
  }

  return cls;
})();

john = new Employee();
john.setName("john");

mary = new Employee();
mary.setName("mary");
mary.increment();

alert("John's name: " + john.getName() + ", age==10: "+john.getAge());
alert("Mary's name: " + mary.getName() + ", age==11: "+mary.getAge());