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 相关文章推荐
判断是否输入完毕再激活提交按钮
Jun 26 Javascript
jquery tools系列 expose 学习
Sep 06 Javascript
Javascript 面向对象之重载
May 04 Javascript
js验证模型自我实现的具体方法
Jun 21 Javascript
jQuery动画效果-fadeIn fadeOut淡入浅出示例代码
Aug 28 Javascript
js插件方式打开pdf文件(浏览器pdf插件分享)
Dec 20 Javascript
详解JavaScript中的表单验证
Jun 16 Javascript
angularjs学习笔记之双向数据绑定
Sep 26 Javascript
微信小程序 教程之引用
Oct 18 Javascript
jQuery实现的模拟弹出窗口功能示例
Nov 24 Javascript
微信小程序开发之录音机 音频播放 动画实例 (真机可用)
Dec 08 Javascript
获取layer.open弹出层的返回值方法
Aug 20 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
杏林同学录(四)
2006/10/09 PHP
PHP 全角转半角实现代码
2010/05/16 PHP
thinkphp3.0输出重复两次的解决方法
2014/12/19 PHP
php swoole多进程/多线程用法示例【基于php7nts版】
2019/08/12 PHP
基于JQuery 选择器使用说明介绍
2013/04/18 Javascript
JS获取URL中的参数数据
2013/12/05 Javascript
浅析JQuery UI Dialog的样式设置问题
2013/12/18 Javascript
解决用jquery load加载页面到div时,不执行页面js的问题
2014/02/22 Javascript
thinkphp实现无限分类(使用递归)
2015/12/19 Javascript
让你一句话理解闭包(简单易懂)
2016/06/03 Javascript
JS和canvas实现俄罗斯方块
2017/03/14 Javascript
JS基于正则表达式的替换操作(replace)用法示例
2017/04/28 Javascript
js实现鼠标跟随运动效果
2020/08/02 Javascript
深入理解Puppeteer的入门教程和实践
2019/03/05 Javascript
D3.js(v3)+react 实现带坐标与比例尺的柱形图 (V3版本)
2019/05/09 Javascript
微信小程序云开发之使用云存储
2019/05/17 Javascript
Vue.js+cube-ui(Scroll组件)实现类似头条效果的横向滚动导航条
2019/06/24 Javascript
从Python程序中访问Java类的简单示例
2015/04/20 Python
python获取当前目录路径和上级路径的实例
2018/04/26 Python
Python WSGI的深入理解
2018/08/01 Python
使用Django连接Mysql数据库步骤
2019/01/15 Python
使用Python实现企业微信的自动打卡功能
2019/04/30 Python
Python数据类型之Dict字典实例详解
2019/05/07 Python
pytorch 自定义参数不更新方式
2020/01/06 Python
解决python 虚拟环境删除包无法加载的问题
2020/07/13 Python
Python中random模块常用方法的使用教程
2020/10/04 Python
Python datetime模块的使用示例
2021/02/02 Python
Manuka Doctor英国官网:真正的麦卢卡蜂蜜和护肤品
2018/10/26 全球购物
TALLY WEiJL法国网上商店:服装、时装及配饰
2019/08/31 全球购物
工作表现自我评价
2014/02/08 职场文书
2014年医院党建工作总结
2014/12/20 职场文书
幼儿园托班教育随笔
2015/08/14 职场文书
团队执行力培训心得体会
2015/08/15 职场文书
2016年万圣节家长开放日活动总结
2016/04/05 职场文书
《传颂之物 虚伪的假面》BD发售宣传CM公开
2022/04/04 日漫
设置IIS Express并发数
2022/07/07 Servers