1.函數做爲形參傳遞
2.函數做爲返回值輸出javascript
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'; });
Array.prototype.sort 接受一個函數看成參數,這個函數裏面封裝了數組元素的排序規則。從Array.prototype.sort 的使用能夠看到,咱們的目的是對數組進行排序,這是不變的部分;而使用什麼規則去排序,則是可變的部分。把可變的部分封裝在函數參數裏,動態傳入
Array.prototype.sort,使 Array.prototype.sort 方法成爲了一個很是靈活的方法。html
let arr = [2,1,3]; arr.sort((a,b)=>{ return a - b; //a-b 從小到大,b-a 從大到小 }) console.log(arr); //[1,2,3]
var getSingle = function ( fn ) { var ret; return function () { return ret || ( ret = fn.apply( this, arguments ) ); }; }; //這個高階函數的例子,既把函數看成參數傳遞,又讓函數執行後返回了另一個函數。咱們 //能夠看看 getSingle 函數的效果: var getScript = getSingle(function(){ return document.createElement( 'script' ); }); var script1 = getScript(); var script2 = getScript(); alert ( script1 === script2 ); // 輸出:true
AOP(面向切面編程)的主要做用是把一些跟核心業務邏輯模塊無關的功能抽離出來,這些跟業務邏輯無關的功能一般包括日誌統計、安全控制、異常處理等。把這些功能抽離出來以後,再經過「動態織入」的方式摻入業務邏輯模塊中。這樣作的好處首先是能夠保持業務邏輯模塊的純淨和高內聚性,其次是能夠很方便地複用日誌統計等功能模塊一般,在 JavaScript 中實現 AOP,都是指把一個函數「動態織入」到另一個函數之中,具體的實現技術有不少,本節咱們經過擴展 Function.prototype 來作到這一點。代碼以下:java
Function.prototype.before = function( beforefn ){ var __self = this; // 保存原函數的引用 return function(){ // 返回包含了原函數和新函數的"代理"函數 beforefn.apply( this, arguments ); // 執行新函數,修正 this return __self.apply( this, arguments ); // 執行原函數 } }; Function.prototype.after = function( afterfn ){ var __self = this; return function(){ var ret = __self.apply( this, arguments ); afterfn.apply( this, arguments ); return ret; } }; var func = function(){ console.log( 2 ); }; func = func.before(function(){ console.log( 1 ); }).after(function(){ console.log( 3 ); }); func();//1 2 3
currying 又稱部分求值。一個 currying 的函數首先會接受一些參數,接受了這些參數以後,該函數並不會當即求值,而是繼續返回另一個函數,剛纔傳入的參數在函數造成的閉包中被保存起來。待到函數被真正須要求值的時候,以前傳入的全部參數都會被一次性用於求值。node
var cost = (function(){ var args = []; return function(){ if ( arguments.length === 0 ){ var money = 0; for ( var i = 0, l = args.length; i < l; i++ ){ money += args[ i ]; } return money; }else{ [].push.apply( args, arguments ); } } })(); cost( 100 ); // 未真正求值 cost( 200 ); // 未真正求值 cost( 300 ); // 未真正求值 console.log( cost() ); // 求值並輸出:600
實現:經過閉包來實現
一個簡單的例子:ajax
//節流 let jieliu = (function (){ let ajax = true; return function(){ console.log(ajax); if(ajax){ ajax = false; let time = setTimeout(function(){ ajax = true; console.log('ajaxing'); },5000); } } })(); document.getElementById('test').onclick = jieliu;
某些函數確實是用戶主動調用的,但由於一些客觀的緣由,這些函數會嚴重地影響頁面性能在短期內往頁面中大量添加 DOM 節點顯然也會讓瀏覽器吃不消,咱們看到的結果每每就是瀏覽器的卡頓甚至假死。代碼以下:編程
var ary = []; for ( var i = 1; i <= 10000000; i++ ){ ary.push( i ); // 假設 ary 裝載了 10000000 個好友的數據 }; var renderFriendList = function( data ){ for ( var i = 0, l = data.length; i < l; i++ ){ var div = document.createElement( 'div' ); div.innerHTML = i; document.body.appendChild( div ); } }; renderFriendList( ary ); //哈哈,界面直接提示崩潰啦
解決方案:分時函數 - 利用setTimeout 每隔一段時間建立dom節點加入界面中,緩解一次性添加過多dom結點形成的低性能問題設計模式
var timeChunk = function( ary, fn, count ){ var obj, t; var len = ary.length; var start = function(){ for ( var i = 0; i < Math.min( count || 1, ary.length ); i++ ){ var obj = ary.shift(); fn( obj ); } }; return function(){ t = setInterval(function(){ if ( ary.length === 0 ){ // 若是所有節點都已經被建立好 return clearInterval( t ); } start(); }, 200 ); // 分批執行的時間間隔,也能夠用參數的形式傳入 }; }; var ary = []; for ( var i = 1; i <= 10000000; i++ ){ ary.push( i ); }; var renderFriendList = timeChunk( ary, function( n ){ var div = document.createElement( 'div' ); div.innerHTML = n; document.body.appendChild( div ); }, 12 ); renderFriendList();
在 Web 開發中,由於瀏覽器之間的實現差別,一些嗅探工做老是不可避免。好比咱們須要一個在各個瀏覽器中可以通用的事件綁定函數 addEvent
新手寫法:數組
var addEvent = function( elem, type, handler ){ if ( window.addEventListener ){ return elem.addEventListener( type, handler, false ); } if ( window.attachEvent ){ return elem.attachEvent( 'on' + type, handler ); } }; //缺點是當它每次被調用的時候都會執行裏面的 if 條件分支,雖然執行這些 if分支的開銷不算大,但也許有一些方法可讓程序避免這些重複的執行過程。
進階寫法:瀏覽器
var addEvent = (function(){ if ( window.addEventListener ){ return function( elem, type, handler ){ elem.addEventListener( type, handler, false ); } } if ( window.attachEvent ){ return function( elem, type, handler ){ elem.attachEvent( 'on' + type, handler ); } } })(); //咱們把嗅探瀏覽器的操做提早到代碼加載的時候,在代碼加載的時候就馬上進行一次判斷,以便讓 addEvent 返回一個包裹了正確邏輯的函數。
缺點:也許咱們從頭至尾都沒有使用過 addEvent 函數,這樣看來,前一次的瀏覽器嗅探就是徹底多餘的操做,並且這也會稍稍延長頁面 ready 的時間。安全
老司機寫法: - 惰性載入函數方案
<html> <body> <div id="div1">點我綁定事件</div> <script> var addEvent = function( elem, type, handler ){ if ( window.addEventListener ){ addEvent = function( elem, type, handler ){ elem.addEventListener( type, handler, false ); } }else if ( window.attachEvent ){ addEvent = function( elem, type, handler ){ elem.attachEvent( 'on' + type, handler ); } } addEvent( elem, type, handler ); }; var div = document.getElementById( 'div1' ); addEvent( div, 'click', function(){ alert (1); }); addEvent( div, 'click', function(){ alert (2); }); </script> </body> </html>