函数传参string_JavaScript 高阶函数

    高阶函数是JavaScript进阶路上经常提到的问题。首先给出高阶函数的定义(参考MDN)。一个返回另外一个函数的函数被称为高阶函数。函数作为参数(回调函数),这里也认为是高阶函数。

返回一个函数

c6bb78e01b4e2ee80380df9a1c1047ba.png

‍借助返回函数,生成了判断多个变量类型的函数。类似checkType 作为一个函数生成器有广泛的用途。

函数作为参数

1f69abff2af65eee426411d05cfd484c.png

函数作为参数,执行回调功能在JavaScript中应用非常广泛。使用回调可以解耦逻辑。

高阶函数之 函数回调地狱

有这样一个场景:

1. 调用 getUserInfo 接口,返回用户信息 userInfo

2. 传参 userInfo.id,调用 getTweetList 接口,返回用户状态列表:tweetList

3. 传参 tweet.id,调用getComments 接口,返回用户状态评论

// 使用上面定义的request方法request(  {url: 'getUserInfo'},   userInfo => {    const { id } = userInfo;    request({      url: 'getTweetList', body: id},      (tweetList = []) => {        const { id } = tweetList[0];        request({          url: 'getComments', body: id         },          comments => {          console.log(comments);        })    })})

在复杂场景下回调函数会产生“回调地狱”的问题。幸好,现在已经有了成熟的解决方案:Promise、Async、Await

回调解决之Promise、Async、Await

async function getComments() {  const { id } = await request({ url: 'getUserInfo' });  const [tweet] = await request({     url: 'getTweetList',     body: id  });  const comments = await request({     url: 'getComments',     body: tweet.id  });  return comments;}

tip: async function 返回是Promise。

基于 Promise、Async、Await 的写法逻辑清晰。对 Promise、Async、Await 的深入讲解就不在这里展开了。

高阶函数之 JavaScript常用方法

[3, 1, 2].sort((a, b) => a - b)// 输出:[1, 2, 3][3, 1, 2].findIndex(v => v === 3)// 输出:0[1,2,3].reduce((a, b) => a + b)// 输出:6[1,2,3].map(v => v * v)// 输出:[1, 4, 9][1,2,3].forEach(v => console.log(v))// 输出:1,2,3[1,2,3].filter(v => v > 1)// 输出:[2, 3]['String', 'Number', 'Object', 'Array', 'Function', 'AsyncFunction', 'Promise'].forEach(v => {  window[`is${v}`] = checkType(v);})

tip:forEach 和 map的区别是,map会返回一个新的数组对象,而forEach不会。

高阶函数之观察者模式:Don't call me, I will call you.

观察者模式在JavaScript中使用非常广泛。页面加载事件,dom事件,mp3、video播放,canvas处理,js、css资源加载。Nodejs整个是架构在观察者模式上的(大部分core module 都继承了events module)。

观察者模式的简单实现

99bcca0553ac334242353cebe7dcdd7b.png

// 观察者模式使用const eventcenter = new EventCenter();eventcenter.on('time-update', time => {  console.log(time);  });const id = setInterval(() => {  eventcenter.emit('time-update', Date.now());  }, 1000);// 停止事件触发setTimeout(() => {  clearInterval(id);});

观察者模式的优势是,逻辑解耦。在设计自己的代码时,可以考虑使用观察者模式进行代码分离。比如设计 http 请求的 request 方法类似jQuery的ajax。

e2f82a4d4e5c70008d550f4ead63e215.png

// 使用 Request 对象const request = new Request();request.on('success', resp => {  console.log(resp);}).on('error', error => {  console.log(error);});request.get({ url: 'request url' });

Request对象继承了EventCenter,拥有了注册、触发事件的能力。成功和失败的回调通过事件注册,进行了解耦。

高阶函数之 Redux Middlewares

const logMiddleware = store => next => action => {  // process business  next(action);}

middleware中每层的 next 是不相同的。观察下下面的方法。

function showLog() {  console.log('showLog');}function enhanceFn(fn) {  return function () {    console.log('log before');    fn();    console.log('log after');  }}showLog = enhanceFn(showLog);// 输出:// log before// showLog// log after

当对 store.dispatch 反复使用类似的逻辑(compose方法),可以产生middleware的效果。

b5c6eb6ead6c243e501ffba4906aaa1a.png

高阶函数之 JavaScript AOP

JavaScript AOP指将一个函数动态织入另一个函数中。

ace3ece1ed0610cfa154d32fd5db923a.png

showLog = enhanceFn(showLog);// 输出:// log before// showLog// log after

动态织入,上面的 enhanceFn 函数也可以实现。vue的实现原理将另一种动态织入的方式让大家熟知。

bef2c2fd8d1329ce69c1b425b415eeb6.png

ES6 里面有了新的解决方案,Proxy 和 Reflex。

const obj = {};const proxy = new Proxy(obj, {  get: function (target, key, receiver) {    return Reflect.get(target, key, receiver);  },  set: function (target, key, value, receiver) {    // 执行变更    Reflect.set(target, key, value, receiver);    // 触发变更事件    eventCenter.emit("time-update", value);    return true;   }  });    // 使用  const timerId = setInterval(() => {    proxy.time = Date.now();    }, 1000);    setTimeout(() => clearInterval(timerId), 1000 * 10);

    高阶函数的应用介绍到这里了,希望对大家有所帮助。欢迎大佬转发支持,提出宝贵意见。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值