搜索:
首页 >> JavaScript >> Js高级编程 >> 第一类工厂与哈希对象

第一类工厂与哈希对象

2009-12-28 来源:Ruby's Louvre 投递文章

第一类工厂相当于mootools的Native方法,用于创建一些具有扩展能力的类,但这些类并没有继承能力,此类工厂也不能以某个类作为蓝本创建子类。总之,一切从简。第一类工厂要依赖一些辅助方法,一并写出来了。

 var dom = {},//命名空间
slice = Array.prototype.slice;
dom.mixin = function (obj, bag) {
  if (arguments.length === 1) {
    bag = obj;
    obj = this;
  };
  if (obj && bag && typeof bag === 'object') {
    for (var p in bag) {
      if(bag.hasOwnProperty(p))
        obj[p] = bag[p];
    }
  };
  if (!+"\v1") {//IE不能在for...in循环中遍历toString与valueOf属性,需要单独处理
    var t = bag.toString,v = bag.valueOf,op = Object.prototype;
    if (bag.hasOwnProperty("toString") && typeof t === "function" && t !== op.toString)
      obj.toString = t;
    if (bag.hasOwnProperty("valueOf") && typeof v === "function" && v !== op.valueOf)
      obj.valueOf = v;
  }
  return obj;
};
dom.factory = function(obj){//第一类工厂
  var init = obj.init,
  klass = function() {
    if(arguments.length === 1 && arguments[0] instanceof klass)
      return arguments[0];
    return new klass.fn.init(arguments);
  }
  klass.fn = klass.prototype = {
    init :init,
    constructor: klass
  };
  klass.fn.init.prototype = klass.fn;
  delete obj.klass;delete obj.init;
  dom.mixin(klass.fn, obj);
  //用于扩展原型方法
  klass.mixin = function(bag){
    dom.mixin(this.fn,bag);
    return this;
  };
  klass.alias = function(oldName, newName){
    var bag = {};
    if (dom.isString(oldName) && dom.isString(newName)){
      var method = this.fn[oldName]
      if (!!method){
        bag[newName] = method;
        return this.mixin(bag);
      };
    };
    //如果是一个属性包,如Hash.alias({keyOf: 'indexOf', hasValue: 'contains'});
    bag = oldName;
    for (var name in bag)
      if(bag.hasOwnProperty(name))
        this.alias(name,bag[name]);
    return this;
  };
  klass.staticizeWithout = function(arr){
    var conditions = {},keys = arr || [],me = this;
    for(var i=0,n = keys.length;i>n;i++){
      conditions[keys[i]] = 1;
    }
    dom.each(me.fn,function(method, name){
      if(!conditions[name] && dom.isFunction(me.fn[name]) && dom.isUndefined(me[name])&&
        name !== 'init' && name !== 'toString' && name !== 'valueOf' ){
        me[name] = function () {
          var args = dom.toArray(arguments),
          caller = args.shift();
          method.name = name; //为其泛化方法添加一个name属性
          return method.apply(me(caller), args);
        }
      }
    });
    return me;
  }
  return klass;
};
dom.mixin(new function(){
  var _toString = Object.prototype.toString,
  _slice = Array.prototype.slice,
  _push = Array.prototype.push,
  is = function(obj,type) {
    return _toString.call(obj).match(/^\[object\s(.*)\]$/)[1] === type;
  }
  return {
    isArray: function (obj) {
      return is(obj,"Array");
    },
    isFunction: function (obj) {
      return is(obj,"Function") ;
    },
    isNumber: function (obj) {
      return is(obj,"Number") ;
    },
    isString: function (obj) {
      return is(obj,"String") ;
    },
    isUndefined: function (obj) {
      return  obj === void(0);
    },
    each: function (obj, fn, bind) {
      for (var key in obj) //只遍历本地属性
        if (obj.hasOwnProperty(key))
          fn.call(bind, obj[key], key, obj);
    },
    isArrayLike : function (obj) {//包括Array
      if(dom.isArray(obj) || obj.callee) return true;
      if(is(obj,'NodeList')) return true;
      if(is(obj,'HTMLCollection')) return true;
      //不能为字符串,不能为window,具有length属性
      if(dom.isNumber(obj.length) && !dom.isString(obj) && !obj.eval){
        if(obj.nextNode || obj.item)
          return true;
        var n = obj.length - 1 > 0 ? 0 : obj.length - 1 ;
        //如果是具有数字键或length属性的对象,如jQuery对象
        if(obj.hasOwnProperty(n) && obj.hasOwnProperty(0))
          return true
        return false;
      }
      return false;
    },
    toArray : function (arr) { //把普通对象变成原生数组对象
      if(arguments.length === 0 || arr === null){
        return [];
      }else if(arr.callee){//如果是Arguments对象
        return _slice.call(arr);
      }else if(dom.isArray(arr)){//如果Array对象返回一个克隆
        return arr.concat();
      }else if(dom.isArrayLike(arr)){
        try{//jQuery对象,dom对象,el.getElementsByTagName得到的HTMLCollection
          //与el.childNodes得到的NodeList
          return _slice.call(arr);
        }catch(e){//IE用slice处理元素或节点集合会出错,只能慢慢拷贝
          var ret = [], i = arr.length;
          while (i) ret[--i] = arr[i]; //Clone数组
          return ret;
        }
      }else {//普通函数,单个元素节点,字符串,数字,window对象
        return [arr];
      }
    },
    setArray: function (els) { //把普通对象变成类数组对象
      this.length = 0;
      _push.apply(this, els);
      return this;
    }
  }
});

这样dom就有如下几个方法mixin,factory,isArray,isArrayLike,isFuction,isNumber,isString,isUndefined,toArray,each,走实用主义路线,像isObject基本没有用。最新版的jQuery1.4a2好像加了两个特别的验证方法,isPlainObject(验证其是javascript core的Object而非宿主对象或DOM对象)与isEmptyObject(空对象,有点像{},但要保证其原型没有被扩展)。

1   2 下一页 尾 页
相关文章
手机版 Js高级编程 Asp之家 Aspxhome.com
闽ICP备06017341号