高阶函数
1.概念
什么是高阶函数
1 2 3
| function a(b) {} a(function (params) { });
|
1 2 3
| function a() { return function (params) {}; }
|
2.应用场景
1.判断类型
举个例子,目前我们判断数据类型有以下几种方法
- typeof
其中 typeof 区分不了 object/array/null (object)
- Object.prototype.toString.call()
- instanceof 1.检测不了用构造函数创建的基本数据类型的值
1 2
| var num=new Number(1); console.log(typeof num);
|
2.instanceof 不仅检测它作用的对象的构造函数,还是检测该对象的原型链的构造函数,只要有一个符合,就会返回 true
比如:
1 2 3 4
| var arr = new Array(); var obj = new Object(); console.log( arr instanceof Object); console.log( arr instanceof Array);
|
- constructor
//原型被覆盖或者继承,constructor 会丢失
综上,我们暂时用 Object.prototype.toString.call()来判断数据类型
1 2 3 4 5 6 7 8 9 10 11
| let typeUtil = {} function isType(type){ return function(content){ Object.prototype.toString.call(content) === `[object ${type}]` } } ["Array","String","Number","Function","Boolean","Date","Null","Undefined"].forEach((type)=>{ typeUtil.["is"+type] = isType(type) }) console.log(typeUtil.isArray([1,2])) console.log(typeUtil.isBoolean(true))
|
首先声明一个高阶函数,然后批量生成类型判断
2.方法劫持
比如一个应用场景,数组增加前要加入某些方法(vue 数据监听),这时候就需要劫持数组的 push 方法
1 2 3 4 5 6 7
| let d = [1, 2, 3]; let oldPush = Array.prototype.push; const mypush = function (...args) { console.log("push以前做一些事情"); oldPush.call(this, ...args); }; mypush(2, 3, 4);
|
3.方法重写
1 2 3 4 5 6 7 8 9 10 11 12
| function a(params) {} Function.prototype.before = function (cb) { return (...args) => { cb(); this(...args); }; }; let fn = a.before(function () { console.log("函数执行前执行某些操作"); }); fn("参数1", "参数2");
|
4.并发
应用场景,接口发送了 2 个请求,这2个请求都结束的时候,需拿到数据并告知做下一步的操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| let getdata = axios.get(url) async function getdata1(){ let data = await getdata('url1') out(data) } async function getdata2(){ let data = await getdata("url2") out(data) }
function fn(arr){ console.log(arr) } function after(cb,times){ let arr = [] return function(data){ arr.push(data) if(--times ===0){ cb(arr) } } } let out = after(fn,2)
|
思考,可以看到高阶函数频繁的使用了闭包
什么叫闭包呢?举个例子:
1 2 3 4 5
| function test() { let c = function () {}; return c; }
|
test 函数中创建了一个 c 函数,c 函数的作用域在 test 中
如果 test()(); //执行完就销毁,不叫闭包
如果 let d = test(); d()执行的时候 c 的执行作用域在 window 下不在 test 下,这就叫闭包,一个函数不在当前作用域执行就叫闭包