Javascriptg高級函數
Javascript高級函數
- 惰性載入函數
- 函數柯裏化
- 級聯函數
這並不全面,只是幾個主要的。
惰性載入函數
惰性載入表示函數執行的分支只會在函數第一次掉用的時候執行,在第一次調用過程中,該函數會被覆蓋為另一個按照合適方式執行的函數,這樣任何對原函數的調用就不用再經過執行的分支了。
寫一個函數用來創建XmlHttpRequest對象,瀏覽器兼容性原因,寫出的代碼通過大量if判斷或者try,catch語句將函數引導到正確代碼處。
代碼示例:
function createXHR(){ var xhr = null; try { // Firefox, Opera 8.0+, Safari,IE7+ xhr = new XMLHttpRequest(); } catch (e) { // Internet Explorer try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); } catch (e) { try { xhr = new ActiveXObject("Microsoft.XMLHTTP"); } catch (e) { xhr = null; } } } return xhr; }
每次調用這個函數的時候,都要先進行瀏覽器能力檢查,首先檢查瀏覽器是否支持內置的XMLHyypRequest對象,如果不支持然後檢查各版本基於ActiveX的XMLHttpRequest,每次調用該函數都是這樣,其實當第一次執行完後,如果瀏覽器支持某個特定XMLHttpRequest對象,那麽下次執行的時候這種支持性並不會改變,沒必要再進行一邊檢測,即使只有一個if語句,執行也肯定比沒有要慢,如果我們可以讓if語句不必每次執行,那麽就可以在頻繁調用的情況下提高執行速度。並且如果在多次createXHR後沒有處理好,還會非常容易造成內存泄漏。解決方案就是惰性載入。在已經判斷出當前瀏覽器是什麽的時候,就讓createXHR == XHR;
function createXHR(){ var xhr=null;
if(typeof XMLHttpRequest !=‘undefined‘){ xhr = new XMLHttpRequest(); createXHR=function(){ return new XMLHttpRequest(); } }else{ try { xhr = new ActiveXObject("Msxml2.XMLHTTP"); createXHR=function(){ return new ActiveXObject("Msxml2.XMLHTTP"); } } catch (e) { try { xhr = new ActiveXObject("Microsoft.XMLHTTP"); createXHR=function(){ return new ActiveXObject("Microsoft.XMLHTTP"); } } catch (e) { createXHR=function(){ return null; } } } } return xhr; }
在這個惰性載入的createXHR中第一次執行的時候每個分支都會為createXHR重新賦值,覆蓋原函數,返回xhr對象,而第二次執行的時候就會直接調用重寫後的函數,這樣就不必執行每個分支重新做檢測了。
函數柯裏化
在計算機科學中,柯裏化(英語:Currying),又譯為卡瑞化或加裏化,是把接受多個參數的函數變換成接受一個單一參數(最初函數的第一個參數)的函數,並且返回接受余下的參數而且返回結果的新函數的技術。
說起函數柯裏化,我理解起來確實費了很大一波力,首先對於代碼中的很多部分都不理解,比如slice、call()、apply()【日後會寫這三個】。理解了這些之後自然能夠看懂柯裏化的通用實現:
代碼示例:
function currying(fn) { var args = Array.prototype.slice.call(arguments, 1); return function () { var innerArgs = Array.prototype.slice.call(arguments); var finalArgs = args.concat(innerArgs); console.log (finalArgs); return fn.apply(this,finalArgs); }; }
- 提高適用性
代碼示例:
function square(i) { return i * i; } function dubble(i) { return i *= 2; } function map(handeler, list) { return list.map(handeler); } // 數組的每一項平方 map(square, [1, 2, 3, 4, 5]); map(square, [6, 7, 8, 9, 10]); map(square, [10, 20, 30, 40, 50]); // ...... // 數組的每一項加倍 map(dubble, [1, 2, 3, 4, 5]); map(dubble, [6, 7, 8, 9, 10]); map(dubble, [10, 20, 30, 40, 50]);
例子中,創建了一個
map
通用函數,用於適應不同的應用場景。。同時,例子中重復傳入了相同的處理函數:square和dubble。應用中這種需要處理的東西會更多。通用性的增強必然帶來適用性的減弱。但是,我們依然可以在中間找到一種平衡。
看下面,我們利用柯裏化改造一下:
代碼示例:
function square(i) { return i * i; } function dubble(i) { return i *= 2; } function map(handeler, list) { return list.map(handeler); } var mapSQ = currying(map, square); mapSQ([1, 2, 3, 4, 5]); mapSQ([6, 7, 8, 9, 10]); mapSQ([10, 20, 30, 40, 50]); // ...... var mapDB = currying(map, dubble); mapDB([1, 2, 3, 4, 5]); mapDB([6, 7, 8, 9, 10]); mapDB([10, 20, 30, 40, 50]); // ......
柯裏化降低通用性,提高適用性。
- 延遲執行
不斷的柯裏化,累計傳入的參數,最後執行。
代碼示例:
var add = function() { var _this = this, _args = arguments return function() { if (!arguments.length) { var sum = 0; for (var i = 0,c; c = _args[i++];) sum += c; return sum; } else { Array.prototype.push.apply(_args, arguments)
return arguments.callee; } } } add(1)(2)(3)(4)();//10柯裏化:
var curry = function(fn) { var _args = [] return function cb() { if (arguments.length == 0) { return fn.apply(this, _args) } Array.prototype.push.apply(_args, arguments); return cb; } }
- 固定易變因素
柯裏化特性決定了它可以提前把易變因素,傳參固定下來,生成一個更明確的應用函數。最典型的代表應用,是bind函數用以固定this這個易變對象。
Function.prototype.bind = function(context) { var _this = this, _args = Array.prototype.slice.call(arguments, 1); return function() { return _this.apply(context, _args.concat(Array.prototype.slice.call(arguments))) } }
但其實我還是沒有那麽透徹的理解函數柯裏化,應該等到其他的知識掌握的更加熟練,理解起來也才會更加容易吧
級聯函數
級聯函數也叫鏈式函數,方法鏈一般適合對一個對象進行連續操作(集中在一句代碼),一定程度上把相關的屬性都連到一起,減少代碼量,缺點是它占用了函數的返回值。
function myclassA(){ this.name=""; this.age=""; this.sex=""; } myclassA.prototype={ setname:function(){ this.name="katherine"; return this; }, setage:function(){ this.age="22"; return this; }, setsex:function(){ this.sex=‘girl‘; return this; } } var me =new myclassA(); console.log(me.setname().setage().setsex()); // myclassA {name: "katherine", age: "22", sex: "girl"}
這一篇整整弄了兩天才弄完,但是還是有些搞不懂函數柯裏化,我想只能在日後的開發中,慢慢接觸項目來解鎖理解了【攤手】
Javascriptg高級函數