专栏首页coding个人笔记Underscore链式调用

Underscore链式调用

在分享之前,先分享一个$通过id的链式调用:

function Fn(elId) { 
  this.el = document.getElementById(elId); 
  return this
}
Fn.prototype.css = function (prop, val) { 
 this.el.style[prop] = val; 
 return this
}
Fn.prototype.hidden = function () { 
  this.css('display', 'none'); 
  return this
}
Fn.prototype.show = function () { 
  this.css('display', 'block'); 
  return this
}
window.$ = function (el) { 
  return new Fn(el)
}
$('test').css('width','300px').css('height','300px').css('background', 'red').hidden().show()

之前分享this的链式调用,上面的代码我们其实可以这样使用:

var fn = new Fn('test');

但是我们不可能每一个id都去创建实例对象,所以这样使用:

window.$ = function (el) { 
  return new Fn(el)
}

当然,这个链式调用非常简陋,只是说明一下思路。

回归今天分享的主题,underscore,这个函数库在业界内很出名,但是本人却从来没用过,估计只有那些算法写的多的才会用吧。underscore兼容了低版本浏览器,实现了对json的遍历。Underscore其实不支持链式调用,想要链式调用需要使用chain方法实现链式调用:

var mapFilter = _.chain([1, 2, 3]).filter(function (a, b, c) { 
   return a > 1}).map(function (a, b, c) { 
   return a > 1}).value()
console.log(mapFilter);//[true, true]

先看一下underscore的三个函数源码:

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

_函数传入一个obj参数,如果是_的实例对象则直接返回,如果不是就返回new _(obj),也就是_实例对象,并且把参数放在wrapped上。

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

调用chain方法,实例一个_实例对象,并赋值chain = true。

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

如果instance里面的chain是true,说明调用了chain方法,就继续调用chain方法,否则直接返回参数obj。

我不知道underscore里面做了什么处理,_(obj).chain() 会报错,因为chain方法是对象_的方法,_(obj)返回的是new _(obj),是实例对象,是没有chain方法的。

这边分享一下,构造函数如果返回的是一个object对象,那么实例对象就是这个object对象,返回基础数据类型都不会。函数其实都有隐式的return undefined:

function Fn() { 
 return {}
}
Fn.prototype.name = 'wade';
var fn = new Fn();

没有return {}的时候:

console.log(fn.name);//wade

有return {}的时候:

console.log(fn.name);//undefined
console.log(fn);//{}

所以这边的chainResult改成:

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

本来想实现map和filter方法,后来发现写不出来,于是就实现push和shift两个最简单的方法。最终代码:

var _ = function(obj) { 
  if (obj instanceof _) return obj; 
  if (!(this instanceof _)) return new _(obj); 
  this._wrapped = obj;
};
_.prototype.shift = function () { 
  this._wrapped.shift(); 
  return chainResult(this, this._wrapped)
}
_.prototype.push = function (num) { 
  this._wrapped.push(num); 
  return chainResult(this, this._wrapped)
}
_.chain = function(obj) { 
  var instance = _(obj); 
  instance._chain = true; 
   return instance;
};
var chainResult = function(instance, obj) { 
  return instance._chain ? _.chain(obj) : obj;
};
console.log(_.chain([1, 2, 3]).push(10).shift()._wrapped)//[2, 3, 10]

我这边没有写value方法,value方法其实就是返回_wrapped。看underscore的源码,你会发现没有多少个函数调用了chainResult,其实underscore有一个遍历添加的方法:

// 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 chainResult(this, func.apply(_, args)); 
  }; 
 }); 
 return _;
};// Add all of the Underscore functions to the wrapper object._.mixin(_);

把所有的方法都调用chainResult。

这就是简单的underscore链式调用的原理,还是那句话,underscore绝对是更复杂的。可以知道一下,本人研究的时候知道了,但是还是不会用,估计一段时间之后还会忘记。

(完)

本文分享自微信公众号 - coding个人笔记(gh_2ce38b49dae1),作者:wade

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-04-17

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • vue nextTick源码

    早之前有分享过vue的nextTick的使用,当时说当数据发生变化,更新后执行回调没有实现,那时候也不知道怎么测试的,其实nextTick方法只是做了一步异步。...

    wade
  • this的指向

    This的指向问题一直是JavaScript的一大核心,很多人都是觉得了解了,但是又模模糊糊。简单概括就是,this的指向永远是指向调用这个this的对象。下面...

    wade
  • 自己实现一个eventBus

    昨天使用了vue提供的事件发布订阅,于是今天就自己实现了一个,发现没有太大难度,直接上代码:

    wade
  • JavaScript设计模式--装饰者模式

    有时我们不希望某个类天生就非常庞大,一次性包含许多职责。那么我们就可以使用装饰着模式。 装饰着模式可以动态地给某个对象添加一些额外的职责,从而不影响这个类中派...

    奋飛
  • 高防服务器-腾讯云高防IP服务器

    高防服务器实际上应该称为高防IP。因为起防护作用的是高防IP,无论你的业务是否在腾讯云,都可以使用腾讯云的高防IP

    用户3570397
  • JS逆向之 RSA 案例汇总

    某团 PASSWORD 参数网址如下: aHR0cHM6Ly9wYXNzcG9ydC5tZWl0dWFuLmNvbS9hY2NvdW50L3VuaXRpdmVs...

    Python编程与实战
  • 高防服务器-腾讯云高防IP服务器

    高防服务器实际上应该称为高防IP。因为起防护作用的是高防IP,无论你的业务是否在腾讯云,都可以使用腾讯云的高防IP

    用户6476787
  • Vue笔记:使用 mock.js 模拟数据

    在我们的项目实际开发过程中,后端的接口往往是较晚才会提供出来,并且还要写接口文档,如果前端的开发都要等到接口开发完成才开始就非常影响项目整体开发进度了,mock...

    朝雨忆轻尘
  • 优秀的数字资产交易平台开发应该具备哪些要素?

    数字资产交易平台开发一直以来注重的无非是用户是否喜欢,再就是平台是否安全,这两大要素也算得上是一个数字资产交易平台开发的核心要素了。数字资产交易平台开发出来是给...

    v-ruiec762679
  • 蓝桥杯之奇怪的比赛

    对一个方阵转置,就是把原来的行号变列号,原来的列号变行号。例如,如下方阵: 1 2 3 4 5 6 7 8 ...

    用户4492257

扫码关注云+社区

领取腾讯云代金券