Änderung des JavaScript-Vererbungsrahmens

  • Ich habe John Resig einfaches JavaScript-Vererbungs-Framework , indem Sie die Set-Funktion mit der Setter-Funktion hinzufügen. Es scheint, dass es funktioniert. Ist es richtig geschrieben? Können Sie unerwünschtes Verhalten sehen? Framework:

     (function(){
       var initializing = false, fnTest = /xyz/.test(function(){xyz;}) ? /\b_super\b/ : /.*/;
       this.Class = function(){};
       Class.extend = function(prop) {
         var _super = this.prototype;
        initializing = true;
        var prototype = new this();
        initializing = false;
        for (var name in prop) {
          prototype[name] = typeof prop[name] == "function" &&
            typeof _super[name] == "function" && fnTest.test(prop[name]) ?
            (function(name, fn){
              return function() {
                var tmp = this._super;
                this._super = _super[name];
                var ret = fn.apply(this, arguments);       
                // CHANGED HERE FROM this._super = tmp;
                // don't like some not used properties 
                if(tmp)this._super = tmp;
                // END OF CHANGE
                return ret;
              };
            })(name, prop[name]) :
            prop[name];
        }
        function Class() {
          if ( !initializing && this.init )
            this.init.apply(this, arguments);
        }
        Class.prototype = prototype;
        Class.prototype.constructor = Class;
        Class.extend = arguments.callee;
    
        // CHANGED HERE
        // Set method
        Class.prototype.set = function(attrs) {
          for (var attr in attrs) {
            //if exist setter function this.on_change{key of wrap: function(key of wrap, new value)
            if(this.on_change[attr])this.on_change[attr].call(this,attr,attrs[attr]);
            else this[attr] = attrs[attr];
          }
          return this;
        };
        if(!Class.prototype.on_change)Class.prototype.on_change={};
        // END OF CHANGE
    
        return Class;
      };
    })();
     

    Testcode:

     var Person = Class.extend({
      a: 15,
      b: 30,
      init: function(){
          //...
      },
      on_change:{
          b: function(oldKey, set){this[oldKey] = set*2}
      }
    });
    var p = new Person();
    p.set({a:25,b:40});
     
    07 December 2011
    Derek B. Bell
1 answer
  • Einfache Frage zuerst: Wird sie richtig geschrieben?

     Class.prototype.set = function(attrs) {
      for (var attr in attrs) {
        //if exist setter function this.on_change{key of wrap: function(key of wrap, new value)
        if(this.on_change[attr])this.on_change[attr].call(this,attr,attrs[attr]);
        else this[attr] = attrs[attr];
      }
      return this;
    };
    if(!Class.prototype.on_change)Class.prototype.on_change={};
     
    • attrs ist kein guter Name, es enthält keine Liste von Attributen, sondern eine Liste von Name / Wert-Paaren. Ich würde vorschlagen, das spartanische o für Object oder möglicherweise map zu verwenden.
    • Das Ablegen der geschweiften Klammern in Ihrer if-Anweisung ist in Ordnung, das Ablegen der Zeilenumbrüche ist nicht so wichtig.
    • Die einzeilige Anmerkung ist nicht sehr hilfreich: \
    • Sie könnten Folgendes für die Initialisierung von on_change verwenden:
      Class.prototype.on_change = Class.prototype.on_change || {};
    • on_change ist nicht lowerCamelCase - & gt; onChange wäre idiomatischer.

    Ich würde dagegen vorschlagen:

     Class.prototype.set = function( map ){
      for ( var attributeName in map ) {
        var value  = map[attributeName],
            setter = this.onChange[attributeName];
        if( setter )
          setter.call( this, attributeName, value );
        else 
          this[attributeName] = value;
      }
      return this;
    };
    Class.prototype.onChange = Class.prototype.onChange || {};
     

    Harte Frage: Sehen Sie unerwünschtes Verhalten?

    Ja.

    1. Wenn onChange alte Skool ist, verwenden reale Ereignisse addEventListener .
    2. Es gibt jetzt zwei Möglichkeiten, eine Eigenschaft zu ändern, indem Sie set und Eigenschaften direkt ändern. Die Setter-Funktionen funktionieren nur für set. Dies führt zu Fehlern.
    3. Sie zählen auf den Setter, der die Zuweisung vornimmt, eine weitere mögliche Fehlerquelle. Ich würde die Zuordnung trotzdem machen, setter in listener umbenennen und dann den Listener ausführen:

       this[attributeName] = value;
      if( listener )
        listener.call( this, attributeName, value );
       
    28 January 2014
    konijnIlya Gazman