美文网首页
Underscore源码阅读:链式调用

Underscore源码阅读:链式调用

作者: San十二 | 来源:发表于2018-11-16 13:49 被阅读0次

chain

_.chain(lyrics)
  .map(function(line) { return line.words.split(' '); })
  .flatten()
  .reduce(function(counts, word) {
    counts[word] = (counts[word] || 0) + 1;
    return counts;
  }, {})
  .value();

Underscore支持链式调用;不过要求函数链的开头要用chain函数生成封装对象。
看看chain到底做了啥。

  _.chain = function (obj) {
    var instance = _(obj);
    instance._chain = true;
    return instance;
  };

chain生成了返回了一个underscore实例

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

我们看到underscore实例就是一个挂载了_wrapper的对象。

再接着,因为_是个构造函数,所有方法都是挂载在构造函数上的。
Underscore提供了mixin方法为Underscore对象进行扩展,我们看看。

  _.mixin = function (obj) {
    _.each(_.functions(obj), function (name) {
      // 对传入的obj,遍历它所有的方法,先挂载在构造函数上
      var func = _[name] = obj[name];
      // 并且所有的方法都会在原型上重写;
      _.prototype[name] = function () {
        var args = [this._wrapped];
        push.apply(args, arguments);
        return result(this, func.apply(_, args));
      };
    });
  };

  _.mixin(_);

Underscore通过mixin将原来挂载在构造函数上所有的方法,全部在_的原型上重写,这次重写,直接指定了underscore所有方法的第一个参数为this._wrapped,也就是构造函数携带的参数。

然后看看最后为了链式调用返回的result函数。明显支持这种“不带”第一个参数的写法是只能写在underscore实例上的。所以在原型上重写的方法,最后返回的仍然是underscore实例。

var result = function (instance, obj) {
    return instance._chain ? _(obj).chain() : obj;
};

也就是说,underscore的链式调用一直返回的是一个_的实例,_的构造方法不仅挂载了全部underscore的方法,并且在原型上重写了这些方法,使得_的实例可以不用传递第一个参数而进行链式调用。

相关文章

网友评论

      本文标题:Underscore源码阅读:链式调用

      本文链接:https://www.haomeiwen.com/subject/caoufqtx.html