underscore之function_动力节点Java学院整理


Posted in Javascript onJuly 11, 2017

因为underscore本来就是为了充分发挥JavaScript的函数式编程特性,所以也提供了大量JavaScript本身没有的高阶函数。

bind

bind()有什么用?我们先看一个常见的错误用法:

'use strict';
console.log('Hello, world!');
// 输出'Hello, world!'
var log = console.log;
log('Hello, world!');
// Uncaught TypeError: Illegal invocation

如果你想用log()取代console.log(),按照上面的做法是不行的,因为直接调用log()传入的this指针是undefined,必须这么用:

'use strict';
var log = console.log;
// 调用call并传入console对象作为this:
log.call(console, 'Hello, world!')
// 输出Hello, world!

这样搞多麻烦!还不如直接用console.log()。但是,bind()可以帮我们把console对象直接绑定在log()的this指针上,以后调用log()就可以直接正常调用了:

'use strict';
var log = _.bind(console.log, console);
log('Hello, world!');
// 输出Hello, world!

partial

partial()就是为一个函数创建偏函数。偏函数是什么东东?看例子:

假设我们要计算xy,这时只需要调用Math.pow(x, y)就可以了。

假设我们经常计算2y,每次都写Math.pow(2, y)就比较麻烦,如果创建一个新的函数能直接这样写pow2N(y)就好了,这个新函数pow2N(y)就是根据Math.pow(x, y)创建出来的偏函数,它固定住了原函数的第一个参数(始终为2):

'use strict';
var pow2N = _.partial(Math.pow, 2);
pow2N(3); // 8
pow2N(5); // 32
pow2N(10); // 1024

如果我们不想固定第一个参数,想固定第二个参数怎么办?比如,希望创建一个偏函数cube(x),计算x3,可以用_作占位符,固定住第二个参数:

'use strict';
var cube = _.partial(Math.pow, _, 3);
cube(3); // 27
cube(5); // 125
cube(10); // 1000

可见,创建偏函数的目的是将原函数的某些参数固定住,可以降低新函数调用的难度。

memoize

如果一个函数调用开销很大,我们就可能希望能把结果缓存下来,以便后续调用时直接获得结果。举个例子,计算阶乘就比较耗时:

'use strict';
function factorial(n) {
  console.log('start calculate ' + n + '!...');
  var s = 1, i = n;
  while (i > 1) {
    s = s * i;
    i --;
  }
  console.log(n + '! = ' + s);
  return s;
}
factorial(10); // 3628800
// 注意控制台输出:
// start calculate 10!...
// 10! = 3628800
用memoize()就可以自动缓存函数计算的结果:
'use strict';
var factorial = _.memoize(function(n) {
  console.log('start calculate ' + n + '!...');
  var s = 1, i = n;
  while (i > 1) {
    s = s * i;
    i --;
  }
  console.log(n + '! = ' + s);
  return s;
});
// 第一次调用:
factorial(10); // 3628800
// 注意控制台输出:
// start calculate 10!...
// 10! = 3628800
// 第二次调用:
factorial(10); // 3628800
// 控制台没有输出

对于相同的调用,比如连续两次调用factorial(10),第二次调用并没有计算,而是直接返回上次计算后缓存的结果。不过,当你计算factorial(9)的时候,仍然会重新计算。

可以对factorial()进行改进,让其递归调用:

'use strict';
var factorial = _.memoize(function(n) {
  console.log('start calculate ' + n + '!...');
  if (n < 2) {
    return 1;
  }
  return n * factorial(n - 1);
});
factorial(10); // 3628800
// 输出结果说明factorial(1)~factorial(10)都已经缓存了:
// start calculate 10!...
// start calculate 9!...
// start calculate 8!...
// start calculate 7!...
// start calculate 6!...
// start calculate 5!...
// start calculate 4!...
// start calculate 3!...
// start calculate 2!...
// start calculate 1!...
factorial(9); // 362880
// console无输出

once

顾名思义,once()保证某个函数执行且仅执行一次。如果你有一个方法叫register(),用户在页面上点两个按钮的任何一个都可以执行的话,就可以用once()保证函数仅调用一次,无论用户点击多少次:

'use strict';
var register = _.once(function () {
  alert('Register ok!');
});
// 测试效果:
register();
register();
register();

 delay

delay()可以让一个函数延迟执行,效果和setTimeout()是一样的,但是代码明显简单了:

'use strict';
// 2秒后调用alert():
_.delay(alert, 2000);
如果要延迟调用的函数有参数,把参数也传进去:
'use strict';
var log = _.bind(console.log, console);
_.delay(log, 2000, 'Hello,', 'world!');
// 2秒后打印'Hello, world!':
Javascript 相关文章推荐
JS修改css样式style浅谈
May 06 Javascript
Jquery遍历节点的方法小集
Jan 22 Javascript
js实现图片拖动改变顺序附图
May 13 Javascript
JavaScript生成的动态下雨背景效果实现方法
Feb 25 Javascript
JS清除文本框内容离开在恢复及鼠标离开文本框时触发js的方法
Jan 12 Javascript
js实现精确到秒的日期选择器完整实例
Apr 30 Javascript
javascript的列表切换【实现代码】
May 03 Javascript
AngularJS中实现动画效果的方法
Jul 28 Javascript
简单实现jQuery弹窗效果
Oct 30 jQuery
WebSocket的通信过程与实现方法详解
Apr 29 Javascript
vue实现城市列表选择功能
Jul 16 Javascript
微信小程序实现滑动操作代码
Apr 23 Javascript
ReactNative实现图片上传功能的示例代码
Jul 11 #Javascript
手把手教你搭建ES6的开发运行环境
Jul 11 #Javascript
ReactNative之键盘Keyboard的弹出与消失示例
Jul 11 #Javascript
react-native 封装选择弹出框示例(试用ios&amp;android)
Jul 11 #Javascript
vue.js内部自定义指令与全局自定义指令的实现详解(利用directive)
Jul 11 #Javascript
javascript 玩转Date对象(实例讲解)
Jul 11 #Javascript
使用jQuery实现动态添加小广告
Jul 11 #jQuery
You might like
有关PHP中MVC的开发经验分享
2012/05/17 PHP
php实现12306余票查询、价格查询示例
2014/04/17 PHP
dedecms中使用php语句指南
2014/11/13 PHP
php等比例缩放图片及剪切图片代码分享
2016/02/13 PHP
PHP接口并发测试的方法(推荐)
2016/12/15 PHP
php集成开发环境详解
2019/09/24 PHP
javascript实现动态增加删除表格行(兼容IE/FF)
2007/04/02 Javascript
关于IE浏览器以及Firefox下的javascript冒泡事件的响应层级
2010/10/14 Javascript
NodeJS url验证(url-valid)的使用方法
2013/11/18 NodeJs
JS批量修改PS中图层名称的方法
2014/01/26 Javascript
jquery+ajax+C#实现无刷新操作数据库数据的简单实例
2014/02/08 Javascript
js处理自己不能定义二维数组的方法详解
2014/03/03 Javascript
js实现改进的仿蓝色论坛导航菜单效果代码
2015/09/06 Javascript
js html5 css俄罗斯方块游戏再现
2016/10/17 Javascript
如何获取元素的最终background-color
2017/02/06 Javascript
cordova入门基础教程及使用中遇到的一些问题总结
2017/11/14 Javascript
jQuery实现input[type=file]多图预览上传删除等功能
2019/08/02 jQuery
Vue 解决通过this.$refs来获取DOM或者组件报错问题
2020/07/28 Javascript
[54:33]2018DOTA2亚洲邀请赛小组赛 A组加赛 Liquid vs Optic
2018/04/03 DOTA
Python编程入门之Hello World的三种实现方式
2015/11/13 Python
python素数筛选法浅析
2018/03/19 Python
Python实现统计英文文章词频的方法分析
2019/01/28 Python
利用 Python ElementTree 生成 xml的实例
2020/03/06 Python
python基于exchange函数发送邮件过程详解
2020/11/06 Python
单身旅行者的单身假期:Just You
2018/04/08 全球购物
SAZAC的动物连体衣和动物睡衣:Kigurumi Shop
2020/03/14 全球购物
zooplus德国:便宜地订购动物用品、动物饲料、动物食品
2020/05/06 全球购物
四年级科学教学反思
2014/02/10 职场文书
工作保证书范文
2014/04/29 职场文书
尊老爱亲美德少年事迹材料
2014/08/14 职场文书
清明节文明祭祀倡议书
2015/04/28 职场文书
创业计划书之健康营养产业
2019/10/15 职场文书
go设置多个GOPATH的方式
2021/05/05 Golang
Python常遇到的错误和异常
2021/11/02 Python
Mysql数据库事务的脏读幻读及不可重复读详解
2022/05/30 MySQL
python解析照片拍摄时间进行图片整理
2022/07/23 Python