Underscore链式调用

在分享以前,先分享一个$经过id的链式调用:css

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');json

可是咱们不可能每个id都去建立实例对象,因此这样使用:浏览器

window.$ = function (el) {  

  return new Fn(el)

}
复制代码

固然,这个链式调用很是简陋,只是说明一下思路。bash

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

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上。ui

_.chain = function(obj) { 

 var instance = _(obj); 

 instance._chain = true; 

 return instance;

};
复制代码

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

var chainResult = function(instance, obj) { 

 return instance._chain ? _(obj).chain() : obj;

};
复制代码

若是instance里面的chain是true,说明调用了chain方法,就继续调用chain方法,不然直接返回参数obj。spa

我不知道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绝对是更复杂的。能够知道一下,本人研究的时候知道了,可是仍是不会用,估计一段时间以后还会忘记。

相关文章
相关标签/搜索