首页 > 代码库 > Underscore.js 分析

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...

Underscore.js 分析