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初学者应注意的七个细节详细介绍
Dec 27 Javascript
Node.js中的流(Stream)介绍
Mar 30 Javascript
JS实现跟随鼠标的链接文字提示框效果
Aug 06 Javascript
js验证身份证号有效性并提示对应信息
Oct 19 Javascript
JavaScript判断图片是否已经加载完毕的方法汇总
Feb 05 Javascript
JS制作图形验证码实现代码
Oct 19 Javascript
Node调用Java的示例代码
Sep 20 Javascript
实例教学如何写vue插件
Nov 30 Javascript
webpack之引入图片的实现及问题
Oct 08 Javascript
微信小程序用户拒绝授权的处理方法详解
Sep 20 Javascript
JQuery事件冒泡和默认行为代码实例
May 13 jQuery
微信小程序返回上一级页面的实现代码
Jun 19 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_MySQL教程-第一天
2007/03/18 PHP
PHP中的命名空间相关概念浅析
2015/01/22 PHP
PHP内置加密函数详解
2016/11/20 PHP
Thinkphp5+plupload实现的图片上传功能示例【支持实时预览】
2019/05/08 PHP
php pdo连接数据库操作示例
2019/11/18 PHP
通过ifame指向的页面高度调整iframe的高度
2006/10/05 Javascript
jquery 选取方法都有哪些
2014/05/18 Javascript
基于NodeJS的前后端分离的思考与实践(五)多终端适配
2014/09/26 NodeJs
jQuery实现悬浮在右上角的网页客服效果代码
2015/10/24 Javascript
AngularJS 中文API参考手册
2016/07/28 Javascript
BootStrap中的Fontawesome 图标
2017/05/25 Javascript
Vue中的作用域CSS和CSS模块的区别
2018/10/09 Javascript
JavaScript作用域链实例详解
2019/01/21 Javascript
微信小程序开发的基本流程步骤
2019/01/31 Javascript
使用webpack编译es6代码的方法步骤
2019/04/28 Javascript
vue history 模式打包部署在域名的二级目录的配置指南
2019/07/02 Javascript
关于layui 弹出层一闪而过就消失的解决方法
2019/09/09 Javascript
[50:12]EG vs Fnatic 2018国际邀请赛小组赛BO2 第二场 8.19
2018/08/21 DOTA
举例讲解Python中的Null模式与桥接模式编程
2016/02/02 Python
python判断字符串是否是json格式方法分享
2017/11/07 Python
python利用插值法对折线进行平滑曲线处理
2018/12/25 Python
使用pyshp包进行shapefile文件修改的例子
2019/12/06 Python
Python进程间通信multiprocess代码实例
2020/03/18 Python
PyQt5中向单元格添加控件的方法示例
2020/03/24 Python
CSS3的Flexbox布局的简明入门指南
2016/04/08 HTML / CSS
法国综合购物网站:RueDuCommerce
2016/09/12 全球购物
Bodum官网:咖啡和茶壶、玻璃器皿、厨房电器等
2018/08/01 全球购物
Tessabit日本:集世界奢侈品和设计师品牌的意大利精品买手店
2020/01/07 全球购物
网上常见的一份Linux面试题(多项选择部分)
2014/09/09 面试题
大学生表扬信范文
2014/01/09 职场文书
教师考核材料
2014/05/21 职场文书
一次性工伤赔偿协议书范本
2014/11/25 职场文书
2014年幼儿园教研工作总结
2014/12/04 职场文书
2015年扶贫帮困工作总结
2015/05/20 职场文书
闪闪的红星观后感
2015/06/08 职场文书
2016年清明节红领巾广播稿
2015/12/17 职场文书