12 链

链模式

解析jQuery

  • 通过$.fn直接返回其原型方法;
  var $ = function () {
    return $.fn;
  }
  $.fn = $.prototype = {
    init: function () {}
  }
  • 添加初始化获取节点方法,并链式返回;
  var $ = function (selector) {
    return $.fn.init(selector);
  }
  $.fn = $.prototype = {
    init: function (selector) {
      this[0] = document.getElementById(selector);
      this.length = 1;
      return this;
    },
    length: 0,
    size: function () {
      return this.length;
    }
  }
  • 覆盖获取
  • 之前没次返回的都是同一个对象,会覆盖;
  • 使用构造函数, 返回的类型为$.fn.$.init => $.fn.init;
  • 注意此时返回的this就不再指向$.fn,再设置$.fn.init.prototype = $.fn;
  • 修改构造器: constructor: $
  var $ = function (selector) {
    return new $.fn.init(selector);
  }
  $.fn = $.prototype = {
    constructor: $,
    init: function (selector) {
      this[0] = document.getElementById(selector);
      this.length = 1;
      return this;
    },
    length: 0,
    size: function () {
      return this.length;
    }
  }
  $.fn.init.prototype = $.fn;
  • 丰富元素获取
  • JS是弱类型语言,并没有纯粹的数组类型,JS引擎的实现也没有做严格校验;一些浏览器解析引擎判断数组时判断length属性,能否[索引值]访问,是否具有些数组方法;
  var $ = function (selector, context) {
    return new $.fn.init(selector, context);
  }
  $.fn = $.prototype = {
    constructor: $,
    init: function (selector, context) {
      this.length = 0;
      context = context || document;
      if (~selector.indexOf('#')) {
        this[0] = document.getElementById(selector.slice(1));
        this.length = 1;
      } else {
        var nodeList = document.querySelectorAll(selector);
        var len = nodeList.length, i = 0;
        for(; i < len; i++) {
          this[i] = nodeList[i];
        }
        this.length = len;
      }

      this.context = context;
      this.selector = selector;
      return this;
    },
    size: function () {
      return this.length;
    },
    //再添加些数组方法,浏览器就会讲返回对象以数组的方式呈现
    push: function () {},
    sort: function () {},
    splice: function () {}
  }
  $.fn.init.prototype = $.fn;
  • 添加方法
  //扩展方法
  $.extend = $.fn.extend = function () {
    var i = 1, len = arguments.length, 
        target = arguments[0], j;
    if(i === len) {
      //原对象为当前对象í
      target = this;
      i--;
    }
    for(; i < len; i++) {
      for(j in arguments[i])
        target[j] = arguments[i][j]
    }
    return target;
  }

  //内部绑定
  $.fn.extend({
    on: (function () {
      //标准DOM2级事件
      if(document.addEventListener) {
        return function (type, fn) {
          var i = this.length - 1;
          for(; i >= 0; i--) {
            this[i].addEventListener(type, fn, false);
          }
          return this;
        }
      } else {
        throw new Error('浏览器不支持标准addEventListener方法')
      }
    })(),
    css: function () {
      var arg = arguments, len = arg.length;
      if(this.length < 1) return this;
      if(len === 1) {
        if(typeof arg[0] === 'string') {
          var name = arg[0], i = 0, l = this.length, results = [];
          if(this[0].currentStyle) {
            for(; i < l; i++) {
              results[i] = this[i].currentStyle[name];
            }
          } else {
            for(; i < l; i++) {
              results[i] = getComputedStyle(this[i], false)[name]
            }
            return results;
          }
        } else if(typeof arg[0] === 'object') {
          for(var i in arg[0]) {
            for(var j = this.length - 1; j >= 0; j--)
              this[j].style[$.camelCase(i) = arg[0][i]];  
          }
        }
      } else if(len === 2) {
        for(var j = this.length - 1; j >= 0 ; j--) {
          this[j].style[$.camelCase(arg[0])] = arg[1];
        }
      }
      return this;
    }
  });

  //外部绑定
  $.extend({
    camelCase: function (str) {
      return str.replace(/\-(\w)/g, function (all, letter) {
        return letter.toUpperCase();
      })
    }
  });
posted @ 2015-10-19 23:41  JinksPeng  阅读(171)  评论(0编辑  收藏  举报