资讯专栏INFORMATION COLUMN

underscore源码分析(1)

李昌杰 / 509人阅读

摘要:版本最主要的一个特性是链式调用我们先简单的实现链式调用的功能实现是很简单的,直接函数就搞定了关键的实现思路也很简单,我们可以这么理解当我们返回了如果想调用方法时,只要把绑定到就可以了我们再把传参传给方法,可参考在线调试因为持续调用所以加入控

underscore 版本1.83 最主要的一个特性是链式调用

_([1,2,3]).each(console.log)
// 1 0 (3) [1, 2, 3]
// 2 1 (3) [1, 2, 3]
// 3 2 (3) [1, 2, 3]

我们先简单的实现链式调用的功能
实现 _.each([1,2,3],console.log) 是很简单的 ,直接_.each函数就搞定了

关键的_().each实现思路也很简单,我们可以这么理解
当我们返回了new _(obj),如果想调用each方法时,只要把each绑定到prototype就可以了
我们再把传参obj传给each方法,可参考_.each.apply(_, args)
jsfiddle在线调试

var _ = function(obj) {
  //因为new _持续调用_, 所以加入if 控制死循环
  if (!(this instanceof _)) return new _(obj);
  //把传入的obj参数保存起来
  this._wrapped = obj;
};

_.each = function(obj, iteratee) {
  var i, length;
  for (i = 0, length = obj.length; i < length; i++) {
       iteratee(obj[i], i, obj);
    }
  return obj;
};

_.prototype.each = function() {
  var args = [this._wrapped];
  [].push.apply(args, arguments);
  return _.each.apply(_, args)
};

_.each([1,2,3],console.log)
_([1,2,3]).each(console.log)

但是 我们怎么实现下面的功能呢?

_([1,2,3]).map(function(a){return a * 2}).each(console.log) //报错
// 2 0
// 4 1
// 6 2

在用underscore的时候我们发现有个_.chain方法,可以实现链式连写

_.chain([1,2,3]).map(function(a){return a * 2}).each(console.log)

// 2 0
// 4 1
// 6 2

我们接下来简单实现
主要的关键点是chainResult函数,返回_(obj).chain()jsfiddle在线调试

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

_.each = function(obj, iteratee) {
  var i, length;
  for (i = 0, length = obj.length; i < length; i++) {
       iteratee(obj[i], i, obj);
    }
  return obj;
};
_.map = function(obj, iteratee, context) {
    var length = obj.length,
        results = Array(length);
    for (var index = 0; index < length; index++) {
      results[index] = iteratee(obj[index], index, obj);
    }
    return results;
  };
 var chainResult = function(instance, obj) {
    return instance._chain ? _(obj).chain() : obj;
  };
  
_.chain = function(obj) {
  var instance = _(obj);
  instance._chain = true;
  return instance;
};

_.prototype.each = function() {
  var args = [this._wrapped];
  [].push.apply(args, arguments);
  return chainResult(this, _.each.apply(_, args))
};
_.prototype.map = function() {
  var args = [this._wrapped];
  [].push.apply(args, arguments);
  return chainResult(this, _.map.apply(_, args))
};
_.prototype.chain = function() {
  var args = [this._wrapped];
  [].push.apply(args, arguments);
  return chainResult(this, _.chain.apply(_, args))
};

_.chain([1,2,3]).map(function(a){ return a * 2}).each(console.log)

我们发现prototype原型链的时候调用的方法都一样的,可以写个函数循环jsfiddle在线调试

function mixin(){
  _.each(["chain", "each", "map"], function(name) {
    var func = _[name]
    _.prototype[name] = function() {
      var args = [this._wrapped];
      [].push.apply(args, arguments);
      return chainResult(this, func.apply(_, args));
    };
  });
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/89841.html

相关文章

  • underscore源码剖析之整体架构

    摘要:我这里有个不够准确但容易理解的说法,就是检查一个对象是否为另一个构造函数的实例,为了更容易理解,下面将全部以是的实例的方式来说。 underscore源码分析之整体架构 最近打算好好看看underscore源码,一个是因为自己确实水平不够,另一个是underscore源码比较简单,比较易读。本系列打算对underscore1.8.3中关键函数源码进行分析,希望做到最详细的源码分析。今...

    2shou 评论0 收藏0
  • underscore源码分析之基础方法

    摘要:在上篇文章整体架构分析中,我们讲过上面的方法有两种挂载方式,一个是挂载到构造函数上以的形式直接调用在后文上统称构造函数调用,另一种则是挂到上以的形式被实例调用在后文上统称原型调用。 underscore源码分析之基础方法 本文是underscore源码剖析系列的第二篇,主要介绍underscore中一些基础方法的实现。 mixin 在上篇文章underscore整体架构分析中,我们讲...

    BigNerdCoding 评论0 收藏0
  • underscore源码该如何阅读?

    摘要:所以它与其他系列的文章并不冲突,完全可以在阅读完这个系列后,再跟着其他系列的文章接着学习。如何阅读我在写系列的时候,被问的最多的问题就是该怎么阅读源码我想简单聊一下自己的思路。感谢大家的阅读和支持,我是冴羽,下个系列再见啦 前言 别名:《underscore 系列 8 篇正式完结!》 介绍 underscore 系列是我写的第三个系列,前两个系列分别是 JavaScript 深入系列、...

    weknow619 评论0 收藏0
  • 学习 underscore 源码整体架构,打造属于自己的函数式编程类库

    摘要:译立即执行函数表达式处理支持浏览器环境微信小程序。学习整体架构,利于打造属于自己的函数式编程类库。下一篇文章可能是学习的源码整体架构。也可以加微信,注明来源,拉您进前端视野交流群。 前言 上一篇文章写了jQuery整体架构,学习 jQuery 源码整体架构,打造属于自己的 js 类库 虽然看过挺多underscore.js分析类的文章,但总感觉少点什么。这也许就是纸上得来终觉浅,绝知此...

    junnplus 评论0 收藏0
  • underscore.js 源码分析之 _.each() 函数

    摘要:遍历中的所有元素,按顺序用遍历输出每个元素。如果传递了参数,则把绑定到对象上。返回以方便链式调用。 each _.each(list, iteratee, [context]) Alias: forEach 遍历list中的所有元素,按顺序用遍历输出每个元素。如果传递了context参数,则把iteratee绑定到context对象上。每次调用iteratee都会传递三个参数:(ele...

    xbynet 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<