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 相关文章推荐
关于hashchangebroker和statehashable的补充文档
Aug 08 Javascript
用jQuery实现的智能隐藏、滑动效果的返回顶部代码
Mar 18 Javascript
js实现键盘控制DIV移动的方法
Jan 10 Javascript
Angular.js自动化测试之protractor详解
Jul 07 Javascript
js实现前端图片上传即时预览功能
Aug 02 Javascript
基于angular6.0实现的一个组件懒加载功能示例
Apr 12 Javascript
微信小程序使用form表单获取输入框数据的实例代码
May 17 Javascript
Vue登录注册并保持登录状态的方法
Aug 17 Javascript
详解关于Vue版本不匹配问题(Vue packages version mismatch)
Sep 17 Javascript
Vue框架TypeScript装饰器使用指南小结
Feb 18 Javascript
JavaScript创建、读取和删除cookie
Sep 03 Javascript
vue input标签通用指令校验的实现
Nov 05 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 Calender(日历)代码分享
2014/01/03 PHP
PHP多线程类及用法实例
2014/12/03 PHP
Jquery为单选框checkbox绑定单击click事件
2012/12/18 Javascript
jQuery-ui引入后Vs2008的无智能提示问题解决方法
2014/02/10 Javascript
JavaScript用select实现日期控件
2015/07/17 Javascript
js仿腾讯QQ的web登陆界面
2016/08/19 Javascript
bootstrap基础知识学习笔记
2016/11/02 Javascript
js格式化时间的简单实例
2016/11/27 Javascript
深入理解Javascript中的观察者模式
2017/02/20 Javascript
node实现简单的反向代理服务器
2017/07/26 Javascript
bootstrap confirmation按钮提示组件使用详解
2017/08/22 Javascript
Three.js中网格对象MESH的属性与方法详解
2017/09/27 Javascript
Angular实现的简单查询天气预报功能示例
2017/12/27 Javascript
Vue实现的父组件向子组件传值功能示例
2019/01/19 Javascript
vue 实现超长文本截取,悬浮框提示
2020/07/29 Javascript
python3序列化与反序列化用法实例
2015/05/26 Python
Python selenium文件上传方法汇总
2020/11/19 Python
python中如何使用正则表达式的非贪婪模式示例
2017/10/09 Python
python字符串格式化方式解析
2019/10/19 Python
python 函数中的参数类型
2020/02/11 Python
Python编程快速上手——Excel表格创建乘法表案例分析
2020/02/28 Python
Python函数基本使用原理详解
2020/03/19 Python
python按照list中字典的某key去重的示例代码
2020/10/13 Python
Html5 语法与规则简要概述
2014/07/29 HTML / CSS
MAC彩妆英国官网:M·A·C UK
2018/05/30 全球购物
面向中国市场的在线海淘美妆零售网站:Beauty House美丽屋
2021/03/02 全球购物
C#面试问题
2016/07/29 面试题
同步和异步有何异同,在什么情况下分别使用他们?
2012/12/28 面试题
加工操作管理制度
2014/01/19 职场文书
商场活动策划方案
2014/01/24 职场文书
幼儿园门卫岗位职责
2014/02/14 职场文书
电气工程及其自动化专业毕业生自荐信
2014/06/21 职场文书
汽车技术服务与贸易专业求职信
2014/07/20 职场文书
商务英语专业大学生职业生涯规划书
2014/09/14 职场文书
股东出资证明书范例
2014/10/04 职场文书
2015年见习期个人工作总结
2015/05/28 职场文书