欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Javascript 是你的高階函數(shù)(高級(jí)應(yīng)用)

 更新時(shí)間:2015年06月15日 17:35:40   投稿:mdxy-dxy  
這篇文章主要介紹了Javascript 是你的高階函數(shù) ,需要的朋友可以參考下

在通常的編程語言中,函數(shù)的參數(shù)只能是基本類型或者對(duì)象引用,返回值也只是基本數(shù)據(jù)類型或?qū)ο笠谩5贘avascript中函數(shù)作為一等公民,既可以當(dāng)做參數(shù)傳遞,也可以被當(dāng)做返回值返回。所謂高階函數(shù)就是可以把函數(shù)作為參數(shù),或者是將函數(shù)作為返回值的函數(shù)。這兩種情形在實(shí)際開發(fā)中有很多應(yīng)用場(chǎng)景,本文是我在工作學(xué)習(xí)中遇到的幾種應(yīng)用場(chǎng)景的總結(jié)。

  回調(diào)函數(shù)

  代碼復(fù)用是衡量一個(gè)應(yīng)用程序的重要標(biāo)準(zhǔn)之一。通過將變化的業(yè)務(wù)邏輯抽離封裝在回調(diào)函數(shù)中能夠有效的提高代碼復(fù)用率。比如ES5中為數(shù)組增加的forEach方法,遍歷數(shù)組,對(duì)每個(gè)元素調(diào)用同一個(gè)函數(shù)。

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

通過回調(diào)函數(shù)將業(yè)務(wù)的重點(diǎn)聚焦在回調(diào)函數(shù)中,而不必每次都要重復(fù)編寫遍歷代碼。

  偏函數(shù)

  作為將函數(shù)當(dāng)做返回值輸出的典型應(yīng)用就是偏函數(shù)。所謂偏函數(shù)是指創(chuàng)建一個(gè)調(diào)用另外一個(gè)部分——參數(shù)或變量已經(jīng)預(yù)置的函數(shù)——的函數(shù)的用法。反正看著定義我是沒理解這東東干嘛的。咱們還是先看例子吧,偏函數(shù)最典型的例子就是類型判斷。

  Javascript對(duì)象都擁有三個(gè)屬性:原型屬性、類屬性、可擴(kuò)展性。(不知道的同學(xué)要回去翻犀牛書哦,page:138)類屬性是一個(gè)字符串,Javascript中并未直接提供,但我們可以利用Object.prototype.toString來間接得到。該函數(shù)總是返回如下形式:

[object Class]  

因此我們可以編寫一系列isType函數(shù)。

代碼如下:

 

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]";
}

 這幾個(gè)函數(shù)中大部分代碼是重復(fù)的,這時(shí)高階函數(shù)便華麗麗的登場(chǎng)了:

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

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

 所以通過指定部分參數(shù)來返回一個(gè)新的定制函數(shù)的形式就是偏函數(shù)。

  currying(柯里化)

  currying又稱部分求值。一個(gè)currying的函數(shù)首先會(huì)接受一些參數(shù),接受這些參數(shù)之后,函數(shù)并不會(huì)立即求值,而是繼續(xù)返回另一個(gè)函數(shù),剛才傳入的參數(shù)在函數(shù)形成的閉包中被保存起來。待到函數(shù)被真正需要求值的時(shí)候,之前傳入的所有參數(shù)都會(huì)被一次性用于求值。

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;
    }
  }
}

假設(shè)我們以計(jì)算一個(gè)月每天花銷為例:

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())

事件節(jié)流

  在某些場(chǎng)景下,某些事件可能會(huì)被重復(fù)的觸發(fā),但事件處理函數(shù)并不需要每次都執(zhí)行。比如在window.resize事件中進(jìn)行復(fù)雜的邏輯計(jì)算,如果用戶頻繁的改變?yōu)g覽器大小,復(fù)雜計(jì)算會(huì)對(duì)性能造成嚴(yán)重影響;有時(shí)這些邏輯計(jì)算并不需要每次rezise時(shí)都觸發(fā),只需要計(jì)算有限的幾次便可以。這時(shí)我們需要根據(jù)時(shí)間段來忽略一些事件請(qǐng)求。請(qǐng)看以下節(jié)流函數(shù):

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);

通過控制函數(shù)執(zhí)行時(shí)間,可以在函數(shù)執(zhí)行次數(shù)與功能需求之間達(dá)到完美平衡。另一個(gè)事件是mousemove。如果我們給一個(gè)dom元素綁定該事件,鼠標(biāo)在改元素上移動(dòng)時(shí),該事件便會(huì)重復(fù)觸發(fā)。

  事件結(jié)束

  對(duì)于某些可以頻繁觸發(fā)的事件,有時(shí)候我們希望在事件結(jié)束后進(jìn)行一系列操作。這時(shí)我們可以利用高階函數(shù)做如下處理:

 

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);

如果在這一過程中事件被觸發(fā)則清除上一次事件句柄,重新綁定執(zhí)行時(shí)間。

參考資料:

《深入淺出node》

《Javascript設(shè)計(jì)模式與開發(fā)實(shí)踐》

相關(guān)文章

最新評(píng)論