日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

深入理解javascript函数进阶系列第一篇——高阶函数

發(fā)布時間:2023/12/10 javascript 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深入理解javascript函数进阶系列第一篇——高阶函数 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前面的話

  前面的函數(shù)系列中介紹了函數(shù)的基礎(chǔ)用法。從本文開始,將介紹javascript函數(shù)進(jìn)階系列,本文將詳細(xì)介紹高階函數(shù)

?

定義

  高階函數(shù)(higher-order function)指操作函數(shù)的函數(shù),一般地,有以下兩種情況

  1、函數(shù)可以作為參數(shù)被傳遞

  2、函數(shù)可以作為返回值輸出

  javascript中的函數(shù)顯然滿足高階函數(shù)的條件,在實(shí)際開發(fā)中,無論是將函數(shù)當(dāng)作參數(shù)傳遞,還是讓函數(shù)的執(zhí)行結(jié)果返回另外一個函數(shù),這兩種情形都有很多應(yīng)用場景。下面將對這兩種情況進(jìn)行詳細(xì)介紹

?

參數(shù)傳遞

  把函數(shù)當(dāng)作參數(shù)傳遞,代表可以抽離出一部分容易變化的業(yè)務(wù)邏輯,把這部分業(yè)務(wù)邏輯放在函數(shù)參數(shù)中,這樣一來可以分離業(yè)務(wù)代碼中變化與不變的部分。其中一個常見的應(yīng)用場景就是回調(diào)函數(shù)

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

  在ajax異步請求的應(yīng)用中,回調(diào)函數(shù)的使用非常頻繁。想在ajax請求返回之后做一些事情,但又并不知道請求返回的確切時間時,最常見的方案就是把callback函數(shù)當(dāng)作參數(shù)傳入發(fā)起ajax請求的方法中,待請求完成之后執(zhí)行callback函數(shù)

var getUserInfo = function( userId, callback ){$.ajax( 'http://xx.com/getUserInfo?' + userId, function( data ){if ( typeof callback === 'function' ){callback( data );}}); } getUserInfo( 123, function( data ){ alert ( data.userName ); });

  回調(diào)函數(shù)的應(yīng)用不僅只在異步請求中,當(dāng)一個函數(shù)不適合執(zhí)行一些請求時,也可以把這些請求封裝成一個函數(shù),并把它作為參數(shù)傳遞給另外一個函數(shù),“委托”給另外一個函數(shù)來執(zhí)行

  比如,想在頁面中創(chuàng)建100個div節(jié)點(diǎn),然后把這些div節(jié)點(diǎn)都設(shè)置為隱藏。下面是一種編寫代碼的方式:

var appendDiv = function(){for ( var i = 0; i < 100; i++ ){var div = document.createElement( 'div' );div.innerHTML = i;document.body.appendChild( div );div.style.display = 'none';} }; appendDiv();

  把div.style.display = 'none'的邏輯硬編碼在appendDiv里顯然是不合理的,appendDiv未免有點(diǎn)個性化,成為了一個難以復(fù)用的函數(shù),并不是每個人創(chuàng)建了節(jié)點(diǎn)之后就希望它們立刻被隱藏

  于是把div.style.display = 'none'這行代碼抽出來,用回調(diào)函數(shù)的形式傳入appendDiv方法

var appendDiv = function( callback ){for ( var i = 0; i < 100; i++ ){var div = document.createElement( 'div' ); div.innerHTML = i;document.body.appendChild( div );if ( typeof callback === 'function' ){callback( div );}} }; appendDiv(function( node ){ node.style.display = 'none'; });

  可以看到,隱藏節(jié)點(diǎn)的請求實(shí)際上是由客戶發(fā)起的,但是客戶并不知道節(jié)點(diǎn)什么時候會創(chuàng)建好,于是把隱藏節(jié)點(diǎn)的邏輯放在回調(diào)函數(shù)中,“委托”給appendDiv方法。appendDiv方法當(dāng)然知道節(jié)點(diǎn)什么時候創(chuàng)建好,所以在節(jié)點(diǎn)創(chuàng)建好的時候,appendDiv會執(zhí)行之前客戶傳入的回調(diào)函數(shù)

【數(shù)組排序】

  函數(shù)作為參數(shù)傳遞的另一個常見場景是數(shù)組排序函數(shù)sort()。Array.prototype.sort接受一個函數(shù)當(dāng)作參數(shù),這個函數(shù)里面封裝了數(shù)組元素的排序方法。目的是對數(shù)組進(jìn)行排序,這是不變的部分;而使用什么規(guī)則去排序,則是可變的部分。把可變的部分封裝在函數(shù)參數(shù)里,動態(tài)傳入Array.prototype.sort,使Array.prototype.sort方法成為了一個非常靈活的方法

// 從小到大排列,輸出: [ 1, 3, 4 ] [ 1, 4, 3 ].sort( function( a, b ){ return a - b; });// 從大到小排列,輸出: [ 4, 3, 1 ] [ 1, 4, 3 ].sort( function( a, b ){ return b - a; });

?

返回值輸出

  相比把函數(shù)當(dāng)作參數(shù)傳遞,函數(shù)當(dāng)作返回值輸出的應(yīng)用場景也有很多。讓函數(shù)繼續(xù)返回一個可執(zhí)行的函數(shù),意味著運(yùn)算過程是可延續(xù)的

  下面是使用Object,prototype.toString方法判斷數(shù)據(jù)類型的一系列的isType函數(shù)

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

  實(shí)際上,這些函數(shù)的大部分實(shí)現(xiàn)都是相同的,不同的只是Object.prototype.toString.call(obj)返回的字符串。為了避免多余的代碼,可以把這些字符串作為參數(shù)提前傳入isType函數(shù)。代碼如下:

var isType = function( type ){ return function( obj ){return Object.prototype.toString.call( obj ) === '[object '+ type +']';} };var isString = isType( 'String' ); var isArray = isType( 'Array' ); var isNumber = isType( 'Number' );console.log( isArray( [ 1, 2, 3 ] ) ); // 輸出:true

  當(dāng)然,還可以用循環(huán)語句,來批量注冊這些 isType 函數(shù):

var Type = {}; for ( var i = 0, type; type = [ 'String', 'Array', 'Number' ][ i++ ]; ){ (function( type ){Type[ 'is' + type ] = function( obj ){return Object.prototype.toString.call( obj ) === '[object '+ type +']';}})( type ) }; Type.isArray( [] ); // 輸出:true Type.isString( "str" ); // 輸出:true

?

AOP

  AOP(面向切面編程)的主要作用是把一些跟核心業(yè)務(wù)邏輯模塊無關(guān)的功能抽離出來,這些跟業(yè)務(wù)邏輯無關(guān)的功能通常包括日志統(tǒng)計(jì)、安全控制、異常處理等。把這些功能抽離出來之后,再通過“動態(tài)織入”的方式摻入業(yè)務(wù)邏輯模塊中。這樣做的好處首先是可以保持業(yè)務(wù)邏輯模塊的純凈和高內(nèi)聚性,其次是可以很方便地復(fù)用日志統(tǒng)計(jì)等功能模塊

  通常,在javascript中實(shí)現(xiàn)AOP,都是指把一個函數(shù)“動態(tài)織入”到另外一個函數(shù)之中。下面通過擴(kuò)展Function.prototype來實(shí)現(xiàn)

Function.prototype.before = function (beforefn) {var _this = this; // 保存原函數(shù)的引用return function () { // 返回包含了原函數(shù)和新函數(shù)的"代理"函數(shù) beforefn.apply(this, arguments); // 先執(zhí)行新函數(shù),修正this return _this.apply(this, arguments); // 再執(zhí)行原函數(shù) }};Function.prototype.after = function (afterfn) {var _this = this;return function () {var ret = _this.apply(this, arguments); //先執(zhí)行原函數(shù)afterfn.apply(this, arguments); //再執(zhí)行新函數(shù)return ret;}};var func = function () {console.log(2);};func = func.before(function () {console.log(1);}).after(function () {console.log(3);});func();

  把負(fù)責(zé)打印數(shù)字1和打印數(shù)字3的兩個函數(shù)通過AOP的方式動態(tài)植入func函數(shù)。通過執(zhí)行上面的代碼,控制臺順利地返回了執(zhí)行結(jié)果1、2、3

//1 //2 //3

?

其他應(yīng)用

【not】

  下面的not函數(shù)用于返回參數(shù)的返回值的邏輯非

function not(f) {return function () {return !(f.apply(this, arguments));};}//偶數(shù)時,返回true;奇數(shù)時,返回falsevar even = function (x) {return x % 2 === 0;}//偶數(shù)時,返回false;奇數(shù)時,返回truevar odd = not(even);[1, 1, 3, 5, 5].every(odd);//true

【mapper】

  下面的mapper()函數(shù),返回的新函數(shù)將一個數(shù)組映射到另一個使用這個函數(shù)的數(shù)組上

//所返回的函數(shù)的參數(shù)應(yīng)當(dāng)是一個實(shí)參數(shù)組,并對每個數(shù)組元素執(zhí)行函數(shù)f(),并返回所有計(jì)算結(jié)果組成的數(shù)組 function mapper(f){return function(a){return Array.prototype.map.call(a,f);} } var increment = function(x){return x+1; } var incrementer = mapper(increment); increment([1,2,3]);//[2,3,4]

【squareofsum】

  下面的函數(shù)接收兩個函數(shù)f()和g(),并返回一個新函數(shù)用以計(jì)算f(g())

//返回一個新的可以計(jì)算f(g(...))的函數(shù) //返回的函數(shù)h()將它所有的實(shí)參傳入g(),然后將g()的返回值傳入f() //調(diào)用f()和g()時的this值和調(diào)用h()時的this值是同一個this function compose(f,g){return function(){//需要給f()傳入一個參數(shù),所以使用f()的call()方法//需要給g()傳入很多參數(shù),所以使用g()的apply()方法return f.call(this,g.apply(this,arguments));}; } var square = function(x){return x*x; } var sum = function(x,y){return x + y; } var squareofsum = compose(square,sum); squareofsum(2,3);//25

  上面代碼中,首先執(zhí)行compose(square,sum)。square傳給f,sum傳給g。然后執(zhí)行f(g())。g作為f函數(shù)的參數(shù),首先執(zhí)行。即先執(zhí)行sum(2,3),結(jié)果為5。再執(zhí)行square(5),最終結(jié)果為25

?

最后

  本文介紹了高階函數(shù)的基礎(chǔ)使用,主要包括參數(shù)傳遞和返回值輸出兩種形式。其中,高階函數(shù)的一個重要應(yīng)用是函數(shù)柯里化(currying),將在下篇博文中詳細(xì)介紹

?

轉(zhuǎn)載于:https://www.cnblogs.com/xiaohuochai/p/8026038.html

總結(jié)

以上是生活随笔為你收集整理的深入理解javascript函数进阶系列第一篇——高阶函数的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。