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 时间格式与时间戳的相互转换示例代码
Dec 25 Javascript
jQuery禁用键盘后退屏蔽F5刷新及禁用右键单击
Jan 22 Javascript
JS两个数组比较,删除重复值的巧妙方法(推荐)
Jun 03 Javascript
AngularJs bootstrap详解及示例代码
Sep 01 Javascript
使用JavaScript获取Request中参数的值方法
Sep 27 Javascript
jquery删除数组中重复元素
Dec 05 Javascript
js实现图片放大展示效果
Aug 30 Javascript
理解Koa2中的async&amp;await的用法
Feb 05 Javascript
Vue兼容ie9的问题全面解决方案
Jun 19 Javascript
通过实例讲解JS如何防抖动
Jun 15 Javascript
如何给element添加一个抽屉组件的方法步骤
Jul 14 Javascript
基于 Vue 的 Electron 项目搭建过程图文详解
Jul 22 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 伪造本地文件包含漏洞的代码
2011/11/03 PHP
php异常处理使用示例
2014/02/25 PHP
用php来限制每个ip每天浏览页面数量的实现思路
2015/02/24 PHP
php实现计算百度地图坐标之间距离的方法
2016/05/05 PHP
详解thinkphp5+swoole实现异步邮件群发(SMTP方式)
2017/10/13 PHP
ThinkPhP+Apache+PHPstorm整合框架流程图解
2020/11/23 PHP
Javascript实例教程(19) 使用HoTMetal(3)
2006/12/23 Javascript
基于jQuery的js分页代码
2010/06/10 Javascript
JS无法捕获滚动条上的mouse up事件的原因猜想
2012/03/21 Javascript
javascript操作html控件实例(javascript添加html)
2013/12/02 Javascript
基于JS实现新闻列表无缝向上滚动实例代码
2016/01/22 Javascript
在JavaScript中call()与apply()区别
2016/01/22 Javascript
AngularJS基础 ng-submit 指令简单示例
2016/08/03 Javascript
vuejs router history 配置到iis的方法
2018/09/20 Javascript
swiper在angularjs中使用循环轮播失效的解决方法
2018/09/27 Javascript
js如何实现元素曝光上报
2019/08/07 Javascript
使用Angular material主题定义自己的组件库的配色体系
2019/09/04 Javascript
vue中使用vue-print.js实现多页打印
2020/03/05 Javascript
40行代码把Vue3的响应式集成进React做状态管理
2020/05/20 Javascript
详解微信小程序入门从这里出发(登录注册、开发工具、文件及结构介绍)
2020/07/21 Javascript
js定时器出现第一次延迟的原因及解决方法
2021/01/04 Javascript
Python 字典(Dictionary)操作详解
2014/03/11 Python
python排序方法实例分析
2015/04/30 Python
浅谈五大Python Web框架
2017/03/20 Python
浅谈python numpy中nonzero()的用法
2018/04/02 Python
wxPython的安装与使用教程
2018/08/31 Python
浅谈python的dataframe与series的创建方法
2018/11/12 Python
Python面向对象程序设计之类的定义与继承简单示例
2019/03/18 Python
python openvc 裁剪、剪切图片 提取图片的行和列
2019/09/19 Python
解决python的空格和tab混淆而报错的问题
2021/02/26 Python
HTML5+CSS3 实现灵动的动画 TAB 切换效果(DEMO)
2017/09/15 HTML / CSS
Expedia韩国官网:亚洲发展最快的在线旅游门户网站
2018/02/26 全球购物
上班时间打瞌睡检讨书
2014/09/26 职场文书
2014卖家双十一活动策划书
2014/09/29 职场文书
2015年社区宣传工作总结
2015/05/20 职场文书
2019销售早会主持词
2019/06/27 职场文书