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 相关文章推荐
javascript 复杂的嵌套环境中输出单引号和双引号
May 26 Javascript
JQuery 学习技巧总结
May 21 Javascript
javascript学习笔记之10个原生技巧
May 21 Javascript
JavaScript类继承及实例化的方法
Jul 25 Javascript
JS截取字符串实例详解
Nov 24 Javascript
jQuery中的AjaxSubmit使用讲解
Sep 25 Javascript
让编辑器支持word复制黏贴、截屏的js代码
Oct 17 Javascript
浅谈JavaScript异步编程
Jan 20 Javascript
判断颜色是否合法的正则表达式(详解)
May 03 Javascript
Vue.js实现网格列表布局转换方法
Aug 25 Javascript
Vue-cli配置打包文件本地使用的教程图解
Aug 02 Javascript
vue实现数据控制视图的原理解析
Jan 07 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
PHP4引用文件语句的对比
2006/10/09 PHP
main.php
2006/12/09 PHP
关于二级目录拖拽排序的实现(源码示例下载)
2013/04/26 PHP
PHP处理JSON字符串key缺少双引号的解决方法
2014/09/16 PHP
PHP实现获取客户端IP并获取IP信息
2015/03/17 PHP
PHP简单实现HTTP和HTTPS跨域共享session解决办法
2015/05/27 PHP
大家须知简单的php性能优化注意点
2016/01/04 PHP
深入浅析PHP的session反序列化漏洞问题
2017/06/15 PHP
laravel实现登录时监听事件,添加登录用户的记录方法
2019/09/30 PHP
优秀js开源框架-jQuery使用手册(1)
2007/03/10 Javascript
传智播客学习之JavaScript基础篇
2009/11/13 Javascript
有趣的javascript数组定义方法
2010/09/10 Javascript
js 动态加载事件的几种方法总结
2013/12/25 Javascript
JS/Jquery判断对象为空的方法
2015/06/11 Javascript
gulp-uglify 与gulp.watch()配合使用时报错(重复压缩问题)
2016/08/24 Javascript
详解Vue方法与事件
2017/03/09 Javascript
js实现随机点名小功能
2017/08/17 Javascript
Django+vue跨域问题解决的详细步骤
2019/01/20 Javascript
JsonProperty 的使用方法详解
2019/10/11 Javascript
提升Python程序运行效率的6个方法
2015/03/31 Python
Python实现压缩和解压缩ZIP文件的方法分析
2017/09/28 Python
Python决策树分类算法学习
2017/12/22 Python
Python深度优先算法生成迷宫
2018/01/22 Python
Python单向链表和双向链表原理与用法实例详解
2018/08/31 Python
python修改字典键(key)的方法
2019/08/05 Python
Python原始套接字编程实例解析
2020/01/29 Python
Python yield生成器和return对比代码实例
2020/04/20 Python
利用Python实现Excel的文件间的数据匹配功能
2020/06/16 Python
Python如何使用input函数获取输入
2020/08/06 Python
最耐用行李箱,一箱永流传:Briggs & Riley(全球终身保修)
2017/12/07 全球购物
Ibood荷兰:互联网每日最佳在线优惠
2019/02/28 全球购物
幼儿园教师培训制度
2014/01/16 职场文书
2015年高中生国庆节演讲稿
2015/07/30 职场文书
2016暑期师德培训心得体会
2016/01/09 职场文书
Jedis操作Redis实现模拟验证码发送功能
2021/09/25 Redis
python绘制云雨图raincloud plot
2022/08/05 Python