高阶函数

高阶函数

Posted by limantang on November 13, 2019

高阶函数

本来想把高阶函数和函数柯里化放在一起讨论的, 想了想还是分开讨论一下吧

什么是高阶函数

高阶函数的定义很简单 把函数当做参数,或者返回值是函数的函数就是高阶函数

高阶函数这个概念很简单, 也很容易理解, 但是讲起来可能会有一些困难

高阶函数举例

Array.prototype.map, Array.prototype.sort, Array.prototype.reduce都是高阶函数 这个应该很容易理解, 因为它们都可以接受函数作为参数

说几个可能没那么容易接受的例子 Function.prototype.bind Function.prototype.apply Fucntion.protortype.call 这几个可能就没那么容易接受了😭 因为我们平时都是这样使用的

function fn() {
	console.log(this);
	console.log('this');
	console.log(this.name);
	console.log('this.name’);
	console.log(arguments);
	console.log('arguments);
}

fn.call({name:'echo'}, 1, 2, 3)
fn.apply({name:'echo'}, [1, 2, 3])
const newFn = fn.bind({name:'echo’}, 1, 2, 3)

单单只看参数的话确实看不出来是高阶函数, bind还好因为最后的返回值是函数, bind很好判断出就是一个高阶函数 那么call和apply呢

下面用一点点数学知识, 使用代入法, 看看call和apply是不是高阶函数, 有什么不对的分析之处或者疑问可以邮箱联系指出问题哈😀

再开始之前有一个点需要强调

// 假设如下代码
const obj = {
	method(a) {
		console.log(this);
		console.log(a);
	}
}
obj.method('a');
//	等同于
obj.method.call(obj, a);

基于上面的代码开始分析

const apply = Function.prototype.apply
function fn() {
	console.log(this);
	console.log('this');
	console.log(this.name);
	console.log('this.name’);
	console.log(arguments);
	console.log('arguments);
}
fn.apply({name: 'echo’}, [1]);
// 带入可得
fn.apply.call(fn, {name: 'echo}, [1])
fn.apply === Function.prototype.apply;

apply.call(fn, {name: echo}, [1]);

最终得到了apply.call(fn, {name: ‘echo’}, [1]);其中apply就是 Function.prototype.apply

在前面讲解this的时候说过对于非箭头函数来说 this其实就是函数的一个隐式的参数, 如果想要自己传参就必须使用call/apply/bind来指定这个隐式的this是什么 所以this就是参数

那么上面得到的apply.call(fn, {name: ‘echo’}, [1])不就是为apply这个函数传入了fn这个函数作为隐式的this吗, 也就是说apply接受函数fn做this, apply符合高阶函数定义, apply就是高阶函数 apply.call(fn, {name: ‘echo’}, [1]) 等价于 fn.apply({name: 'echo}, [1])

最后在解释一下apply.call(fn, {name: ‘echo’}, [1])这个函数里面三个参数的意义

fn作为apply的隐式参数this, 传递给apply这个函数使用 {name: 'echo'}作为fn这个函数的隐式参数this, 传递给函数fn使用 [1]这个参数是apply这个函数的最后一个参数, 最终数组的每一项作为fn的实参来使用

最后在举一个关于bind类似的🌰

const bind = Function.prototype.bind
function fn() {
	console.log(this);
	console.log('this');
	console.log(this.name);
	console.log('this.name’);
	console.log(arguments);
	console.log('arguments);
}
const newFn = fn.bind({name: 'echo’}, 1, 2);
// 带入可得

fn.bind({name: 'echo}, 1, 2);
// 等价于
fn.bind.call(fn, {name: 'echo’}, 1, 2);

fn.bind === Function.prototype.bind;

fn.bind.call(fn, {name: 'echo}, 1, 2);
// 等价于
bind.call(fn, {name: 'echo’}, 1, 2);

分析过程和上面类似 , 感兴趣的同学可以自己理一理这个过程