解读rightjs的继承机制2

Class.Methods是一个方法集合,把经常用到的方法移出函数体是一个陪明的做法,这样不就用每次进入函数体就反复创建它们。

从另一个角度看,Class.Methods是自动执行函数,YUI的人好像把它归类为模块模式,EXT这样的用法很多,把许多变量与只对当前模块有用的方法捆绑在一个闭包中,减少命名冲突。

 
      Class.Methods = (function() {
        //一系列方法名,可以看到include涉及最多东西
        var commons = $w('selfExtended self_extended selfIncluded self_included'),
        extend  = commons.concat($w('prototype parent extend include')),
        include = commons.concat(['constructor']);
        //用来清理模块中不需要的方法
        //相当于module.without(extend)或module.without(include)
        function clean_module(module, what) {
          return Object.without.apply(Object, [module].concat(what == 'e' ? extend : include));
        };

        return {
           //方法集合
        }
      })();

上面有些写法很不妥,如 commons.concat(['constructor']),直接commons.concat('constructor')就可以了。不过最大的问题是Object.without方法:

 
  without: function() {
    var filter = $A(arguments), object = filter.shift(), copy = {}, key;
    for (key in object)
      if (!filter.includes(key))
        copy[key] = object[key];

    return copy;
  },

在IE下,for...in循环是有许多属性不能遍历出来的,如valueOf、toString……

看inherit方法,它暗中运用了桥梁模式,使用子类与父类的原型不再连在一起。而且通过new原型的方法,比属性拷贝快很多。

 
inherit: function(parent) {
    // 获取父类的原型属性
    if (parent && parent.prototype) {
      var s_klass = function() {};
      s_klass.prototype = parent.prototype;
      this.prototype = new s_klass;
      this.parent = parent;
    }
    // 收集父类
    this.ancestors = [];
    while (parent) {
      this.ancestors.push(parent);
      parent = parent.parent;
    }
   //修正原型上的constructor属性
    return this.prototype.constructor = this;
  },

下面方法为新类扩展静态成员,这是ruby的写法,在jQuery,无论是为jQuery命名空间添加成员还是为jQuery对象添加实例方法都是用extend,比较无言。

 
extend: function() {
    $A(arguments).filter(isHash).each(function(module) {
     //用于实现ruby的那种自扩展机制
      var callback = module.selfExtended || module.self_extended;

      $ext(this, clean_module(module, 'e'));

      if (callback) callback.call(module, this);
    }, this);

    return this;
  },

include则为新类扩展原型成员,也是ruby的命名方式。在mootools中,则为implement。觉得mootools与rights从ruby中借鉴了不少东西啊。ruby果然是最强的OO脚本语言。

 
      include: function() {
        //取得所有超类的原型
        var ancestors = this.ancestors.map('prototype'), ancestor;
        //移参数转换为纯对象数组并迭代它们
        $A(arguments).filter(isHash).each(function(module) {
          //用于ruby式的自包含
          var callback = module.selfIncluded || module.self_included;
          //清理一些危险的方法,防止覆盖
          module = clean_module(module, 'i');

          for (var key in module) {
            //取得最近的与它有重名方法的祖先
            ancestor = ancestors.first(function(proto) { return isFunction(proto[key]); });
            //如果有,则重写此方法,返回一个currying
            this.prototype[key] = !ancestor ? module[key] :
              (function(name, method, super_method) {
              return function() {
                //用于方法链
                this.$super = super_method;
                return method.apply(this, arguments);
              };
            })(key, module[key], ancestor[key]);
          }
          //执行自包含
          if (callback) callback.call(module, this);
        }, this);

        return this;
      }

此外,Class还有一个方法,不过作为辅助方法,不加入类工厂中的。

 
//从当前类或其祖先中,寻找特定的属性
Class.findSet = function(object, property) {
  var upcased = property.toUpperCase(), capcased = property.capitalize(),
    candidates = [object, object.constructor].concat(object.constructor.ancestors),
    holder = candidates.first(function(o) { return o && (o[upcased] || o[capcased]) });

  return holder ? holder[upcased] || holder[capcased] : null;
};
原文地址:https://www.cnblogs.com/rubylouvre/p/1701524.html