Underscore.js 分析

Underscore.js的源码和适合第一次看源码的人,因为文件比较小,而且没有依赖,读起来比较轻松。代码写的还很是很简练的。

我看的是1.7的源码,下面说说我觉得比较有意思的几个地方

1. 

_.isUndefined = function(obj) {
    return obj === void 0;
};

代码里好几个地方都用到了void 0,而不是undefined判断一个object是不是undefined。据说这样是因为有些浏览器允许改变undefined的值。比如undefined = 1

2.

以前用jQuery的时候就用到过noConflict,一直在好奇是怎么实现的。原来Underscore.js里的实现这么简单

var root = this;

var previousUnderscore = root._;

_.noConflict = function() {
    root._ = previousUnderscore;
    return this;
};

3. 

Underscore.js支持两种方式调用,一种是直接用_.func(params)调用,还有以类似oop的方式调用

_.each([‘a‘, ‘b‘, ‘c‘], function(element, index){
    console.log(element);
});

_([‘a‘, ‘b‘, ‘c‘]).each(function(element, index){
    console.log(element);
});

这是怎么做到的呢?

首先,定义了_下面的函数,比如

  _.each = _.forEach = function(obj, iteratee, context) {
    if (obj == null) return obj;
    iteratee = createCallback(iteratee, context);
    var i, length = obj.length;
    if (length === +length) {
      for (i = 0; i < length; i++) {
        iteratee(obj[i], i, obj);
      }
    } else {
      var keys = _.keys(obj);
      for (i = 0, length = keys.length; i < length; i++) {
        iteratee(obj[keys[i]], keys[i], obj);
      }
    }
    return obj;
  };

如果把javascript中的对象看作类,这样的定义就类似定义了类 ‘_’的static成员函数,直接通过 _.func就可以调用。但是 类‘_‘的实例 new _(),是不能调用的。

 

只是oop主要靠下面的两个函数

 var _ = function(obj) {
    if (obj instanceof _) return obj;
    if (!(this instanceof _)) return new _(obj);
    this._wrapped = obj;
  };


  // Add your own custom functions to the Underscore object.
  _.mixin = function(obj) {
    _.each(_.functions(obj), function(name) {
      var func = _[name] = obj[name];
      _.prototype[name] = function() {
        var args = [this._wrapped];
        push.apply(args, arguments);
        return result.call(this, func.apply(_, args));
      };
    });
  };

  // Add all of the Underscore functions to the wrapper object.
  _.mixin(_);

先看第一个函数,当调用_([‘a‘, ‘b‘, ‘c‘])的时候,第一个函数会执行。它做的事情就是把一个obj变成了‘_‘的一个实例(new _()),并且把obj存到该实例的_wrapped中。

该函数的实现也很有意思。当调用_[‘a‘, ‘b‘, ‘c‘]的时候,第一次执行到第二句,this是全局的window, 因此if(!(this instanceof _)) 成立,所以执行new _(obj),这时候第二次进入该函数,此时的this已经是新的_ instance实例,因此直接执行到了第三行,即把this_wrapped赋值为obj。

TBC...

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。