特性概览
- 函数是“第一等公民”
函数和其他数据类型一样,处于平等地位,可以赋值
给其他变量,可以作为参数
,可以作为其他函数的返回值
- 只用“表达式”,不用“语句”
“表达式”是一个单纯的运算过程,总有返回值
,“语句”是执行某种操作,没有返回值 - 没有副作用,不修改状态
函数式编程只返回新的值
,不修改系统变量
目录
- 纯函数(pure function)
- 柯里化
- 函数的合成
- 高阶函数
- 回调
- 递归
- 立即执行函数
- 惰性函数
- 偏函数
纯函数
- 一个函数的返回结果只依赖与它的参数
var a = 1; function func(b){ return a +b; } func(2); // 3 a = 2; func(2); // 4 //func受到外部变量影响了 // 修正 function func(a, b){ return a+b }
- 在执行过程中没有副作用
var obj = { age: 1 } function func(obj, b){ obj.age += 1; return obj.age + b; } func(obj, 1); console.log(obj); // { age: 2 } 外部变量obj被篡改了 //修正 function func(obj, b){ var age = obj.age + 1; return age + b; }
柯里化
柯里化(Currying)是把接受多个
参数的函数变换成接受一个单一
参数(最初函数的第一个参数)的函数,并且返回接受余下的参数且返回结果的新函数的技术
//柯里化之前
function add(x,y){
return x+y
}
add(1,2) //3
//柯里化之后
function addC(x){
return function(y){
return x+y
}
}
addC(1)(2) //3
柯里化通用实现前端开发者进阶之函数柯里化Currying
function currying(fn){
var slice = Array.prototype.slice,
_args = slice.call(arguments,1)
return function(){
var _inargs = slice.call(arguments)
return fn.apply(null, _args.concat(_inargs))
}
}
链式调用函数
const compose = function(f){
return function(g){
return function(x){
return f(g(x))
}
}
}
compose(f)(g)(x)
//链式调用函数
函数的合成
高阶函数
函数可以作为参数被传递
常见于回调函数callback,也称函数传递
var getUserInfo = function(userId,callback){
$.ajax(url+userId,function(data){
if(typeof callback === 'function'){
callback(data)
}
})
}
//使用
getUserInfo(13157,function(data){
console.log(data)
})
PS:
Array.prototype.sort
也接受函数作为参数,还有each
,filter
等等
函数可以作为返回值输出
单例模式初探版
var getSingle = function(fn){
var ret;
return function(){
return ret || (ret = fn.apply(this,arguments))
}
}
回调
封装一个Function.prototype.method,让它看起来像回调函数。
Function.prototype.method = function(name, func){
if(!this.prototype[name]){
this.prototype[name] = func
}
return this;
}
// 使用
// 判断数字的正负
Number.method('integer', function(){
return Math[this < 0 ? 'ceil' : 'floor'](this)
})
// 移除字符串首尾空白的方法
String.method('trim', function(){
return this.replace(/^\s+|\s+s/g, '')
})
递归
斐波那契数列
//一共10级楼梯,每次可以走一步或两步,求一共多少种走法。
//公式:f(n)=f(n-1)+f(n-2)
function f(n){
if(n==1){
return 1
}else if(n==2){
return 2
}else {
return f(n-1)+f(n-2)
}
}
尾递归
function fibonacci(n){
function _fibonacci(n,n1,n2){
if(n <=1){
return n2
}
return _fibonacci(n,n2,n1+n2)
}
return _fibonacci(n,1,1)
}
在ES6中尾递归可以这样写,不过需要在'use strict'模式下
'use strict'
function fibonacci(n, n1 = 1, n2 = 1){
if(n<=1) return n2
return fibonacci(n, n2, n1+n2)
}
立即执行函数
IIFE
;(function(data){
console.log(data) //asd
})('asd');
(function(global){
console.log(global) //window
//构造函数
function Set(){
this._values = []
}
Set.prototype['log'] = function(){console.log(this._values)}
global.Set = Set;
})(this)
//使用
var set = new Set()
set.log() //[]
惰性函数
惰性函数(lazy-functions)就是解决每次都要进行判断的这个问题,解决原理很简单,重写函数。
实例:兼容现代浏览器与IE的addEvent事件
一般写法
function addEvent(type, el, fn) {
if(window.addEventListener){
el.addEventListener(type, fn, false)
}
else if(window.attachEvent){
el.attachEvent('on'+type, fn)
}
}
惰性函数写法
function addEvent(type, el ,fn){
if(window.addEventListener){
addEvent = function(type, el ,fn){
el.addEventListener(type, fn, false)
}
}
else if(window.attachEvent){
addEvent = function(type, el ,fn){
el.attachEvent('on'+type, fn)
}
}
}
偏函数
JavaScript专题之偏函数
什么是偏函数
:固定函数的第一个或几个参数,返回一个新函数,接收剩下的参数。
英语:partial,又称局部应用
,bind()
就是典型的偏函数
function add(a, b) {
return a + b;
}
var addOne = add.bind(null, 1);
addOne(2) // 3