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

这是执行JS OOP的好方法吗?

  •  8
  • fphilipe  · 技术社区  · 17 年前

    我用以下方式编写JS类。

    var MyClass = function() {
        // private vars
        var self = this,
            _foo = 1,
            _bar = "test";
    
        // public vars
        this.cool = true;
    
        // private methods
        var initialize = function(a, b) {
            // initialize everything
        };
    
        var doSomething = function() {
            var test = 34;
            _foo = cool;
        };
    
        // public methods
        this.startRequest = function() {
    
        };
    
        // call the constructor
        initialize.apply(this, arguments);
    };
    
    var instance_1 = new MyClass();
    var instance_2 = new MyClass("just", "testing");
    

    这是一个好方法吗?有什么缺点吗? 我不使用继承,但它会以这种方式实现继承吗?

    6 回复  |  直到 16 年前
        1
  •  6
  •   Javier    17 年前

    我认为这是一个非常好的方法。不要为“没有继承权”的问题感到羞耻。大多数面向对象编程与继承无关。最重要的方面是封装和多态性,您已经掌握了它们。

    可以说(嗯,我通常认为)继承只适用于静态语言,您必须以某种方式告诉编译器这两种类型(类)是相关的,它们有一些共同点(共同祖先),以便允许多态性。对于动态语言,OTOH,编译器不会在意,运行时环境将在没有任何继承的情况下找到共性。

    另外一点:如果你在某些地方需要一些继承(而且是 伟大的 在某些情况下,例如GUI),通常您会发现可以轻松地在“简单”对象/类和其他更复杂、更重的对象/类之间进行互操作。IOW:不要试图找到一个满足你所有需求的框架,并将其用于所有事情;相反,只要有助于解决具体问题,就可以在每一时刻使用你觉得更舒服的方法。

        3
  •  2
  •   cwallenpoole    17 年前

    事实上,这与Prototype.js(我最喜欢的库)通常的做法没有什么不同。如果你看这里:

    var Class = (function() {
      function subclass() {};
    
      // All classes are created through Class.create( {/*JSON Object*/} );
      // or Class.create( function, ...properties );
      // The first form will create a unique class.
      // The second form will create a Class which subclasses the initial function.
      function create() {
    
        var parent = null, 
                         // $A just normalizes the array.
            properties = $A(arguments);
    
        // Which type of class definition was used?
        if (Object.isFunction(properties[0]))
          parent = properties.shift();
    
        // This effectively creates a constructor
        function klass() {
          this.initialize.apply(this, arguments);
        }
    
        // Allows klass to have addMethods property
        Object.extend(klass, Class.Methods);
        klass.superclass = parent;
        klass.subclasses = [];
    
        // Does this class have a parent class?
        if (parent) {
          subclass.prototype = parent.prototype;
          klass.prototype = new subclass;
          parent.subclasses.push(klass);
        }
    
        // Add methods to the class
        for (var i = 0; i < properties.length; i++)
          klass.addMethods(properties[i]);
    
        // emptyFunction = function(){};
        if (!klass.prototype.initialize)
          klass.prototype.initialize = Prototype.emptyFunction;
    
        // Creates the constructor
        klass.prototype.constructor = klass;
        return klass;
      }
    
      function addMethods(source) {
        // Does this class have a parent?
        var ancestor   = this.superclass && this.superclass.prototype;
    
        // Grab the keys of a JSON object
        var properties = Object.keys(source);
    
        // Makes sure each object has a toString and valueOf method.
        if (!Object.keys({ toString: true }).length) {
          if (source.toString != Object.prototype.toString)
            properties.push("toString");
          if (source.valueOf != Object.prototype.valueOf)
            properties.push("valueOf");
        }
    
        //Loop through the properties.
        for (var i = 0, length = properties.length; i < length; i++) {
    
          // property is the Key in the JSON, value is the corresponding
          // method or property value.
          var property = properties[i], value = source[property];
          if (ancestor && Object.isFunction(value) &&
              value.argumentNames().first() == "$super") {
    
            // Handles an override of a parent method.
            var method = value;
            value = (function(m) {
              return function() { return ancestor[m].apply(this, arguments); };
            })(property).wrap(method);
    
            value.valueOf = method.valueOf.bind(method);
            value.toString = method.toString.bind(method);
          }
          this.prototype[property] = value;
        }
    
        return this;
      }
    
      // And here is the final value!
      return {
        create: create,
        Methods: {
          addMethods: addMethods
        }
      };
    })();
    

    上面的好处是,您将能够快速、轻松地管理继承。在您的情况下,如果不创建某种形式的外部辅助函数(如上所述),继承(或至少重写函数)几乎是不可能的。

        4
  •  1
  •   Christopher Parker    17 年前

    我一直认为Douglas Crockford的网站是JavaScript最佳实践的宝贵资源。碰巧他写了几篇与你的问题有关的文章。

        5
  •  0
  •   Chris S. Chris S.    17 年前
        6
  •  0
  •   Gabor de Mooij    14 年前

    您也可以只使用文本和生成器。这样,您就不必使用Javascript中不太吸引人的概念:原型、新语句和This关键字。

    • 创建一个构建文字对象的函数
    • 将该函数放入文本对象中

    具有生成器的文本充当类。生成器函数充当构造函数,生成的文本充当类实例。

    以下是一个例子:

    Car = {
        createNew:function() { //no prototype!
            var obj = {};
            var color;
            obj.setColor = function(c) { color = c; }
            obj.drive = function(){ alert('driving a '+color+' car'); }
            return obj; //no this-keyword!
        }
    }
    
    var car = Car.createNew(); //no new statement!
    car.setColor('red');
    car.drive();
    

    更多文档可在此处找到:

    http://www.gabordemooij.com/jsoop.html

    这里呢

    https://github.com/schuttelaar/Rococo2/wiki/Getting-started