简介
什么是函数式编程?
百科定义:函数式编程是种编程方式,它将电脑运算视为函数的计算。函数编程语言最重要的基础是λ演算(lambda calculus),而且λ演算的函数可以接受函数当作输入(参数)和输出(返回值)。
函数式编程强调没有"副作用",意味着函数要保持独立,所有功能就是返回一个新的值,没有其他行为,尤其是不得修改外部变量的,在javascript中,对于数组的操作,有些是纯函数,有些是不纯的
var arr = [1, 2, 3, 4, 5]
//纯函数
arr.slice(0, 3) //不会改变arr的值,arr = [1, 2, 3, 4, 5]
//非纯函数
arr.splice(0, 3) //会改变arr的值,arr = [4, 5]
underscore使用了函数式的特性,提供了一系列函数式方法,underscore会把自身绑定到唯一的全局变量 _ 上
_.each([1, 2, 3], alert);
=> alerts each number in turn...
_.map([1, 2, 3], function(num){ return num * 3; });
=> [3, 6, 9]
_.map({one: 1, two: 2, three: 3}, function(num, key){ return num * 3; });
=> [3, 6, 9]
_.map([[1, 2], [3, 4]], _.first);
=> [1, 3]
//去重
_.uniq([1, 2, 1, 4, 1, 3]);
=> [1, 2, 4, 3]
_.indexOf([1, 2, 3], 2);
=> 1
源码解读
初始化
underscore初始化,underscore在一个自执行函数里面执行代码,防止全局污染
(function(){
//javascript self对象指窗口本身,它返回的对象跟window对象是一模一样的,也正因为如此,window对象的常用方法和函数都可以用self代替windo。下面相当于 root = window
var root = typeof self == 'object' && self.self === self && self || typeof global == 'object' && global.global === global && global || this || {}
var _ = function(obj) { //underscore构造函数
}
root._ = _ //将 _ 挂载到window对象上
})()
调用方式
underscore有两种调用方式,一种函数式风格,一种面向对象风格
// 函数式风格
_.each([1, 2, 3], function(item){
console.log(item)
});
// 面向对象风格
_([1, 2, 3]).each(function(item){
console.log(item)
});
第二种面向对象的风格,_([1, 2, 3])返回的是underscore实例,相当于 new _(),该实例再调用each方法,如何实现这一功能呢?underscore跟jquery实现还是有区别的,jquery使用的是共享原型的方式,下面是underscore方式
var _ = function(obj) {
if (!(this instanceof _)) return new _(obj);
this._wrapped = obj;
}
- 首次执行_()方法,this指的是window对象,所以会执行return new _(obj)
- 执行new _(obj)时候,this这时候指的是 _,会将 this. _warpped指向obj,即传进来的数据 [1, 2, 3]
mixin方法
上面说了undersore有两种调用方式,underscore源码内部都是 _ .map()=function、_ .each=function(){}这样的方式调用,mixin方法就是为了合并两种调用方式,同时将这些方法挂载到underscore原型上
var ArrayProto = Array.prototype;
var push = ArrayProto.push;
//判断obj是否是函数
_.isFunction = function(obj) {
return typeof obj == 'function' || false;
};
//返回一个保存obj中的方法名称的数组
_.functions = function(obj) {
var names = [];
for (var key in obj) {
if (_.isFunction(obj[key])) names.push(key);
}
return names.sort();
};
_.mixin = function(obj) {
_.each(_.functions(obj), function(name) { //name是underscore所拥有的所有方法名称(each,map...)
var func = _[name] = obj[name];
_.prototype[name] = function() { //给underscore原型上扩展each、map等方法
var args = [this._wrapped]; //this._wrapped是储存传入的数据,即第二种风格传入的数据
push.apply(args, arguments); //将数据跟传入的参数合并 [this.wrapped, ...arguments]
return func.apply(_, args); //执行underscore内部方法,即执行第一种风格方法
};
});
return _;
};
_.mixin(_);