闭包与高阶函数

JS闭包与高阶函数

闭包与高阶函数@TOC

闭包与高阶函数

事实上闭包与高阶函数在js中很常见。

1 闭包

当函数可以记住并访问所在的词法作用域时,就产生了闭包。即使函数在当前函数的作用域之外执行。
例子:

function foo() { 
	var a = 2
	function bar() { 
		console.log(a) 
	} 
	return bar 
} 
var baz = foo() baz() // 输出: 2

1.1 利用闭包实现结果缓存

例子:

/**
 * 闭包备忘函数,
 * 假如add是一个很复杂的计算函数,如果每次运行,则需要消耗大量的空间和时间,利用闭包
 * 特性,将之前的状态进行保存 这样就可以在第二次调用的时候,直接输出结果,而不需要重
 * 新计算,则节省了空间的消耗。
 *  */ 
function add(a) {
    return a + 1;
}

function memorise(fn) {
    var cache = {};
    return function (){
        var args = Array.prototype.slice.call(arguments);
        var key = JSON.stringify(args);
        return cache[key] || (cache[key] = fn.apply(fn, args));
    }    
}

var addrs = memorise(add); 
console.log(addrs(1));
console.log(addrs(2));
console.log(addrs(3));
console.log(addrs(2));
    

2高阶函数

2.1 函数作为参数

典型的应用比如就是回调函数。
比如:

setTimeout(function() {
	console.log("这是一个回调函数");
}, 1000);

// 钩子函数
function mainFunc(callback)  {
	callback();
}

2.2 函数作为返回值(闭包)

function Fun() {
	return function bar() {
		console.log("this is a closure");
	}
}

2.2.1 柯里化

柯里化(currying),又称为部分求值,是把多个参数的原函数变换成为接受单一参数的函数,并且返回一个新的函数,新函数能够接受余下的参数,最后返回同原函数一样的结果。
作用
(1)参数复用
(2)提前返回
(3)延迟计算/运行
通用实现:

/**
 * Currie 柯里化 通用实现
 */

function curryingEs5(fn) {
    var rest1 = Array.prototype.slice.call(arguments);  // 用来记录默认参数的参数数组
    rest1.shift();
    return function() {
        var rest2 = Array.prototype.slice.call(arguments); // 用来记录传入的参数
        return fn.apply(null, rest1.concat(rest2));
    }
}

// function curryingEs6(fn, ...rest1) {
//     return function(...rest2) {
//         return fn.apply(null, rest1.concat(rest2));
//     }
// }

function sayHello(name, age, hobby) {
    console.log("my name is " + name + " my age is " + age + " years old and my hobby is " + hobby);
}

var curryingTest = curryingEs5(sayHello, "xaiogang");
curryingTest("26", "play pingpong ball");

2.2.2 反柯里化

扩大适用范围,创建一个应用范围更加广的函数,使得原本只有特定对象才适用的方法,扩展到更多的对象。
例子:

function unCurryingEs5(fn) {
     return function (tar) {
         var rest = Array.prototype.slice.call(arguments);
         rest.shift();
         return fn.apply(tar, rest);
     }
 }

 var push = unCurryingEs5(Array.prototype.push);

 function exePush() {
     push(arguments, 4);
     console.log(arguments);
 }

 exePush(1, 2, 3);

偏函数

偏函数是创建一个调用另外一部分的函数,函数可以根据传入的参数来生成一个真正执行的函数。其本身不包含我们真正需要的逻辑代码,只是根据传入的参数返回其他的函数,返回的函数中才含有真正的处理逻辑。

/**
  * 偏函数
  */
var isType = function(type) {
    return function(obj) {
        return Object.prototype.toString.call(obj) === `[object ${type}]`
    }
}
var isString = isType("String");
var a = "nihao";
console.log(isString(a));
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值