[读书笔记]高阶函数
生活随笔
收集整理的這篇文章主要介紹了
[读书笔记]高阶函数
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
1. 什么是高階函數
- 函數可以作為參數被傳遞;
- 函數可以作為返回值輸出。
2. 高階函數的示例
2.1 函數作為參數傳遞
(1) 回調函數(callback)
回調函數類似于C#中的委托,在異步操作中應用較為廣泛。如jQuery中的ajax:
1 var getOrderInfo = function (callback) { 2 $.ajax({ 3 type: 'POST', 4 url: '/URL', 5 data: "name=John&location=Boston", 6 dataType: "json", 7 }).then(function (data) { 8 if (typeof callback === 'function') { 9 // render 10 callback(data); 11 } 12 }, function () { 13 console.error('error'); 14 }); 15 };(2) Array.prototype.sort
將排序規則作為回調函數傳給Array.prototype.sort方法來得到想要的排序結果:
1 var s1 = [ 2 { name: '李雷', age: 12 }, 3 { name: '陳梅梅', age: 11 }, 4 { name: '露西', age: 11 }, 5 { name: '大衛', age: 13 } 6 ], 7 s2 = [].concat(s1), 8 ageAsc = function (a, b) { 9 return a.age - b.age; 10 }, 11 ageDesc = function (a, b) { 12 return b.age - a.age; 13 }; 14 // 年齡從小到大 15 s1.sort(ageAsc); 16 console.dir(s1); 17 // 年齡大到小 18 s2.sort(ageDesc); 19 console.info(s2);2.2 函數作為返回值輸出
(1) 判斷數據類型
1 var isType = function( type ){ 2 return function( obj ){ 3 return Object.prototype.toString.call( obj ) === '[object '+ type +']'; 4 } 5 }, 6 isString = isType( 'String' ), 7 isArray = isType( 'Array' ), 8 isNumber = isType('Number'); 9 console.log(isString); // 輸出isString 10 /* 11 function( obj ){ 12 return Object.prototype.toString.call( obj ) === '[object '+ type +']'; 13 } 14 */(2) 獲取單例
1 var getSingle = function (fn) { 2 var ret; 3 return function () { 4 return ret || (ret = fn.apply(this, arguments)); 5 }; 6 }, 7 getScript = getSingle(function () { 8 return document.createElement('script'); 9 }); 10 11 var script1 = getScript(), // 第一次調用時將執行 (ret = fn.apply(this, arguments) 12 script2 = getScript(); // 第二次調用時直接返回 ret 13 console.log('script1 === script2 is ', script1 === script2); // 輸出:true3. 高階函數的應用
3.1 高階函數實現AOP
提起AOP(面向切面編程),可能會想起Spring MVC 中的AOP。實現如下:
1 Function.prototype.before = function (beforefn) { 2 var that = this; // 保存原函數的引用 3 console.log(that); // that指向print2() 4 // 返回包含了原函數和新函數的"代理"函數 5 // return#1 6 return function () { 7 beforefn.apply(this, arguments); // 執行新函數,修正this 8 return that.apply(this, arguments); // 執行原函數 9 }; 10 }; 11 12 Function.prototype.after = function (afterfn) { 13 var that = this; // 保存原函數的引用 14 console.log(that); // that 指向return#1 15 // return#2 16 return function () { 17 var ret = that.apply(this, arguments); // 執行原函數,并保存原函數的執行結果 18 afterfn.apply(this, arguments); // 執行新函數 19 return ret; // 在新函數執行完成之后返回原函數的執行結果 20 }; 21 }; 22 23 var print1 = function () { 24 console.log(1); 25 }, 26 print2 = function () { 27 console.log(2); 28 }, 29 print3 = function () { 30 console.log(3); 31 }; 32 33 print2 = print2.before(print1).after(print3); 34 print2();3.2 柯里化(currying)
currying 又稱部分求值。一個currying 的函數首先會接受一些參數,接受了這些參數之后,
該函數并不會立即求值,而是繼續返回另外一個函數,剛才傳入的參數在函數形成的閉包中被保
存起來。待到函數被真正需要求值的時候,之前傳入的所有參數都會被一次性用于求值。
3.3 反柯里化(uncurrying)
1 Function.prototype.uncurrying = function () { 2 var self = this; 3 return function () { 4 return Function.prototype.call.apply(self, arguments); 5 } 6 }; 7 8 var push = Array.prototype.push.uncurrying(); 9 10 var obj = { 11 name: 'wills', 12 age: 26 13 }; 14 push(obj, 'JavaScript programer'); 15 16 console.log(obj); // Object {0: "JavaScript programer", name: "wills", age: 27, length: 1}3.4 函數節流
函數節流目的即降低函數被頻繁調用的頻率。代碼實現如下:
1 // 函數節流 2 var throttle = function (fn, interval) { 3 var __self = fn, // 保存需要被延遲執行的函數引用 4 timer, // 定時器 5 firstTime = true; // 是否是第一次調用 6 7 return function () { 8 var args = arguments, 9 that = this; 10 11 // 如果是第一次調用,不需延遲執行 12 if (firstTime) { 13 __self.apply(that, args); 14 return firstTime = false; 15 } 16 17 if (timer) { // 如果定時器還在,說明前一次延遲執行還沒有 18 return false; 19 } 20 21 timer = setTimeout(function () { // 延遲一段時間執行 22 clearTimeout(timer); 23 timer = null; 24 __self.apply(that, args); 25 }, interval || 500); 26 }; 27 }; 28 29 var resizeThrottle = throttle(function () { 30 console.log(1); 31 }, 500), 32 resize = function () { 33 console.log(2); 34 }; 35 window.onresize = function () { 36 resizeThrottle(); 37 resize(2); 38 };3.5 分時函數
?分時函數與函數節流相似,使用場景一般為主動調用。
1 var ary = []; 2 for (var i = 1; i <= 1000; i++) { 3 ary.push(i); // 假設ary 裝載了1000 個好友的數據 4 }; 5 var renderFriendList = function (data) { 6 for (var i = 0, l = data.length; i < l; i++) { 7 var div = document.createElement('div'); 8 div.innerHTML = i; 9 document.body.appendChild(div); 10 } 11 }; 12 renderFriendList(ary); 未使用分時函數優化前使用分時函數之后:
var timeChunk = function (ary, fn, count) {/// <summary>/// 分時函數/// </summary>/// <param name="ary" type="Array">數據(對象)數組</param>/// <param name="fn" type="Function">函數</param>/// <param name="count" type="Number">每次執行的數組長度</param>var obj,t,len = ary.length,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 <= 1000; i++) {ary.push(i); }; var renderFriendList = timeChunk(ary, function (n) {var div = document.createElement('div');div.innerHTML = n;document.body.appendChild(div); }, 8);renderFriendList();3.6 惰性加載函數
?
1 var addEvent = function (elem, type, handler) { 2 console.log('addEvent'); 3 if (window.addEventListener) { 4 console.log('addEventListener'); 5 addEvent = function (elem, type, handler) { 6 elem.addEventListener(type, handler, false); 7 } 8 } else if (window.attachEvent) { 9 console.log('attachEvent'); 10 addEvent = function (elem, type, handler) { 11 elem.attachEvent('on' + type, handler); 12 } 13 } 14 addEvent(elem, type, handler); 15 }; 16 17 var div = document.getElementById('div1'); 18 addEvent(div, 'click', function () { 19 alert(1); 20 }); 21 addEvent(div, 'click', function () { 22 alert(2); 23 });?
轉載于:https://www.cnblogs.com/January/p/5430764.html
《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀總結
以上是生活随笔為你收集整理的[读书笔记]高阶函数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: static方法与非static方法是否
- 下一篇: 链剖LCT总结