Javascript 是你的高阶函数(高级应用)


Posted in Javascript onJune 15, 2015

在通常的编程语言中,函数的参数只能是基本类型或者对象引用,返回值也只是基本数据类型或对象引用。但在Javascript中函数作为一等公民,既可以当做参数传递,也可以被当做返回值返回。所谓高阶函数就是可以把函数作为参数,或者是将函数作为返回值的函数。这两种情形在实际开发中有很多应用场景,本文是我在工作学习中遇到的几种应用场景的总结。

回调函数

代码复用是衡量一个应用程序的重要标准之一。通过将变化的业务逻辑抽离封装在回调函数中能够有效的提高代码复用率。比如ES5中为数组增加的forEach方法,遍历数组,对每个元素调用同一个函数。

array = {};
array.forEach = function(arr, fn){
  for (var i = 0, len = arr.length; i < len; i++) {
    fn(arr[i], i, arr);
  }
}

通过回调函数将业务的重点聚焦在回调函数中,而不必每次都要重复编写遍历代码。

  偏函数

作为将函数当做返回值输出的典型应用就是偏函数。所谓偏函数是指创建一个调用另外一个部分——参数或变量已经预置的函数——的函数的用法。反正看着定义我是没理解这东东干嘛的。咱们还是先看例子吧,偏函数最典型的例子就是类型判断。

Javascript对象都拥有三个属性:原型属性、类属性、可扩展性。(不知道的同学要回去翻犀牛书哦,page:138)类属性是一个字符串,Javascript中并未直接提供,但我们可以利用Object.prototype.toString来间接得到。该函数总是返回如下形式:

[object Class]

因此我们可以编写一系列isType函数。

代码如下:

 

isString = function(obj){
  return Object.prototype.toString.call(obj) === "[object String]";
}
isNumber = function(obj){
  return Object.prototype.toString.call(obj) === "[object Number]";
}
isArray = function(obj){
  return Object.prototype.toString.call(obj) === "[object Array]";
}

 这几个函数中大部分代码是重复的,这时高阶函数便华丽丽的登场了:

isType = function(type) {
  return function(obj) {
    return Object.prototype.toString.call(obj) === "[object " + type + "]";
  }
}

isString = isType('String');
isNumber = isType('Number');
isArray = isType('Array');

 所以通过指定部分参数来返回一个新的定制函数的形式就是偏函数。

currying(柯里化)

currying又称部分求值。一个currying的函数首先会接受一些参数,接受这些参数之后,函数并不会立即求值,而是继续返回另一个函数,刚才传入的参数在函数形成的闭包中被保存起来。待到函数被真正需要求值的时候,之前传入的所有参数都会被一次性用于求值。

var currying = function(fn) {
  var args = [];
  
  return function() {
    if (arguments.length === 0) {
      return fn.applay(this, args);
    } else {
      args = args.concat(arguments);
      return arguments.callee;
    }
  }
}

假设我们以计算一个月每天花销为例:

var currying = function(fn) {
debugger;
  var args = [];
  
  return function() {
    if (arguments.length === 0) {
      return fn.apply(this, args);
    } else {
      Array.prototype.push.apply(args, arguments);
      return arguments.callee;
    }
  }
}

cost = function(){
  var sum = 0;
  for (var i = 0, len = arguments.length; i < len; i++) {
    sum += arguments[i];
  }
  
  return sum;
}
var cost = currying(cost);

cost(100);
cost(200);
alert(cost())

事件节流

在某些场景下,某些事件可能会被重复的触发,但事件处理函数并不需要每次都执行。比如在window.resize事件中进行复杂的逻辑计算,如果用户频繁的改变浏览器大小,复杂计算会对性能造成严重影响;有时这些逻辑计算并不需要每次rezise时都触发,只需要计算有限的几次便可以。这时我们需要根据时间段来忽略一些事件请求。请看以下节流函数:

function throttle(fn, interval) {
   var doing = false;

   return function() {
    if (doing) {
     return;
    }
    doing = true;
    fn.apply(this, arguments);
    setTimeout(function() {
     doing = false;
    }, interval);
   }
  }
  
  window.onresize = throttle(function(){
    console.log('execute');
  }, 500);

通过控制函数执行时间,可以在函数执行次数与功能需求之间达到完美平衡。另一个事件是mousemove。如果我们给一个dom元素绑定该事件,鼠标在改元素上移动时,该事件便会重复触发。

事件结束

对于某些可以频繁触发的事件,有时候我们希望在事件结束后进行一系列操作。这时我们可以利用高阶函数做如下处理:

 

function debounce(fn, interval) {
  var timer = null;

 function delay() {
  var target = this;
  var args = arguments;
  return setTimeout(function(){
   fn.apply(target, args);
  }, interval);
 }

 return function() {
  if (timer) {
   clearTimeout(timer);
  }

  timer = delay.apply(this, arguments);
 }
};
window.onresize = throttle(function(){
  console.log('resize end');
}, 500);

如果在这一过程中事件被触发则清除上一次事件句柄,重新绑定执行时间。

参考资料:

《深入浅出node》

《Javascript设计模式与开发实践》

Javascript 相关文章推荐
js form 验证函数 当前比较流行的错误提示
Jun 23 Javascript
jquery CSS选择器笔记
Mar 29 Javascript
一些老手都不一定知道的JavaScript技巧
May 06 Javascript
JavaScript获取路径设计源码
May 22 Javascript
jquery显示隐藏input对象
Jul 21 Javascript
JS+CSS实现可以凹陷显示选中单元格的方法
Mar 02 Javascript
js实现文字闪烁特效的方法
Dec 17 Javascript
JSON 数据详解及实例代码分析
Jan 20 Javascript
jQuery读取XML文件的方法示例
Feb 03 Javascript
微信小程序-横向滑动scroll-view隐藏滚动条
Apr 20 Javascript
通过源码分析Vue的双向数据绑定详解
Sep 24 Javascript
JS基于对象的特性实现去除数组中重复项功能详解
Nov 17 Javascript
Javascript 高阶函数使用介绍
Jun 15 #Javascript
jQuery预加载图片常用方法
Jun 15 #Javascript
简述JavaScript中正则表达式的使用方法
Jun 15 #Javascript
简介JavaScript中用于处理正切的Math.tan()方法
Jun 15 #Javascript
在JavaScript中使用开平方根的sqrt()方法
Jun 15 #Javascript
JavaScript中的Math.sin()方法使用详解
Jun 15 #Javascript
JavaScript中用于四舍五入的Math.round()方法讲解
Jun 15 #Javascript
You might like
php获取网页内容方法总结
2008/12/04 PHP
防止本地用户用fsockopen DDOS攻击对策
2011/11/02 PHP
PHP COOKIE及时生效的方法介绍
2014/02/14 PHP
PHP读取大文件的类SplFileObject使用介绍
2014/04/09 PHP
完美利用Yii2微信后台开发的系列总结
2016/07/18 PHP
php编程实现简单的网页版计算器功能示例
2017/04/26 PHP
javascript新手语法小结
2008/06/15 Javascript
简明json介绍
2008/09/28 Javascript
Jquery 滑入滑出效果实现代码
2010/03/27 Javascript
date.parse在IE和FF中的区别
2010/07/29 Javascript
jquery的Tooltip插件 qtip使用详细说明
2010/09/08 Javascript
始终在屏幕中间显示Div的代码(css+js)
2011/03/10 Javascript
JavaScript DOM 编程艺术(第2版)读书笔记(JavaScript的最佳实践)
2013/10/01 Javascript
JS 页面计时器示例代码
2013/10/28 Javascript
详解JavaScript中的blink()方法的使用
2015/06/08 Javascript
老生常谈onBlur事件与onfocus事件(js)
2016/07/09 Javascript
VueJS组件之间通过props交互及验证的方式
2017/09/04 Javascript
antd-mobile ListView长列表的数据更新遇到的坑
2020/04/08 Javascript
浅谈vue-props的default写不写有什么区别
2020/08/09 Javascript
python使用xlrd模块读写Excel文件的方法
2015/05/06 Python
Random 在 Python 中的使用方法
2018/08/09 Python
利用Pycharm断点调试Python程序的方法
2018/11/29 Python
ActiveMQ:使用Python访问ActiveMQ的方法
2019/01/30 Python
python查询文件夹下excel的sheet名代码实例
2019/04/02 Python
Django项目中实现使用qq第三方登录功能
2019/08/13 Python
ubuntu 安装pyqt5和卸载pyQt5的方法
2020/03/24 Python
pytorch加载自己的图像数据集实例
2020/07/07 Python
CSS3 实现的缩略图悬停效果
2020/12/09 HTML / CSS
amazeui 验证按钮扩展的实现
2020/08/21 HTML / CSS
GIVENCHY纪梵希官方旗舰店:高定彩妆与贵族护肤品
2018/04/16 全球购物
关于祖国的演讲稿
2014/05/04 职场文书
岗位说明书范文
2014/05/07 职场文书
2014大学生中国梦主题教育学习思想汇报
2014/09/10 职场文书
党员批评与自我批评发言稿
2014/10/14 职场文书
万能检讨书开头与结尾怎么写
2015/02/17 职场文书
详解Nginx的超时keeplive_timeout配置步骤
2022/05/25 Servers