如果你仔細看了到目前為止出現過的範例程式碼,你會發現這裡面的一些方法不太熟悉。 它們是map()、filter()和reduce()函數,它們對任何語言的函數式程式設計都至關重要。 它們可以讓你不必使用迴圈和語句,寫出更簡潔的程式碼。
map()、filter()和reduce()函數組成了函數式程式設計師工具集的核心部分,這個工具集包括一系列純粹的、 高階的函數,它們是函數式方法的主力。實際上,它們是純函數和高階函數的典型,它們以一個函數為輸入, 傳回一個輸出結果,並且不會產生副作用。
然而它們是瀏覽器中ECMAScript 5.1的實作標準,它們只工作於陣列。每次呼叫它們,一個新的數組會被創建並返回, 而原來存在的數組不會被改變。它們以函數為輸入,並經常使用匿名函數作為回調函數。它們遍歷數組, 並對數組的每個元素應用這個函數!
myArray = [1,2,3,4]; newArray = myArray.map(function(x) {return x*2}); console.log(myArray); // Output: [1,2,3,4] console.log(newArray); // Output: [2,4,6,8]
還有一點,它們只作用於數組,無法作用於其它可迭代的資料結構,例如物件。不用擔心, 有很多函式庫例如Underscore.js,Lazy.js,stream.js等等都實作了它們自己的更強大的map()、 filter()和reduce()。
回呼
如果你以前從來沒用過回調,那這個概念可能會讓你有些迷惑。尤其是在Javascript中, Javascript給了好幾種宣告函數的方式。
回呼函數用來傳遞給另一個函數供它們使用,這是一種像傳遞物件一樣來傳遞邏輯的方式:
var myArray = [1,2,3]; function myCallback(x){return x+1}; console.log(myArray.map(myCallback));
對於比較簡單的任務可以用匿名函數:
console.log(myArray.map(function(x){return x+1}));
回呼不僅用於函數式編程,在Javascript中它們能幹很多事情。僅作為例子,這有一個callback()函數用於jQuery的AJAX呼叫:
function myCallback(xhr) { console.log(xhr.status); return true; } $.ajax(myURI).done(myCallback);
注意這裡只用了函數的名字,因為我們不是要呼叫函數而是傳遞函數,寫成這樣就錯了:
$.ajax(myURI).fail(myCallback(xhr)); // 或者 $.ajax(myURI).fail(myCallback());
如果我們呼叫了函數會發生什麼事?在這個範例裡,myCallback(xhr)會嘗試執行,控制台將列印“undefined”, 並會傳回true。當ajax()完成呼叫時,它根據名字找到的回調函數將是一個"true",然後就報錯了。
也就是說我們無法指定給回呼函數傳什麼參數,如果我們的回呼函數需要讓ajax()函數傳給他我們想要的參數, 我們可以把回到函數包在一個匿名函數裡:
function myCallback(status) { console.log(status); return true; } $.ajax(myURI).done(function(xhr) { myCallback(xhr.status) });
Array.prototype.map()
map()是這些函數的老大,它簡單地對陣列裡的元素依此套用回呼函數。
文法:arr.map(callback [, thisArg]);
參數:
•callback(): 這個函數為新陣列產生一個元素,它所接收的參數: ◦currentValue:陣列目前遍歷到的元素
◦index:數組中目前元素序數
◦array:目前正在處理的陣列
•thisArg:這是一個可選參數,當執行回呼的時候它作為回呼函數的this
範例:
var integers = [1, -0, 9, -8, 3], numbers = [1, 2, 3, 4], str = 'hello world how ya doing?'; // 将整数映射为他们自己的绝对值 console.log(integers.map(Math.abs)); // 将数组中的元素与自己的位置序数相乘 console.log(numbers.map(function(x, i) { return x * i })); // 单词隔一个变一个大写 console.log(str.split(' ').map(function(s, i) { if (i % 2 == 0) return s.toUpperCase(); else return s; }));
儘管Array.prototype.map方法是Javascript中陣列物件的標準方法,你也可以很容易地擴充自己的物件。
MyObject.prototype.map = function(f) {  return new MyObject(f(this.value)); };
Array.prototype.filter()
filter()函數用來篩選數組中的一些元素。回呼函數必須傳回真(保留到新數組裡)或假(丟掉)。 用map()可以做類似的事情,就是把你像丟掉的元素回傳為null,不過filter()函數會在新數組裡面刪除這些不要的元素, 而不是留個null佔著位置。
語法:arr.filter(callback [, thisArg]);
•callback():這個函數用來測試陣列中的每個元素,要保留回傳真,否則回傳假。它有這些參數: ◦currentValue:數組目前遍歷到的元素
◦index:數組中目前元素的序數
◦array:目前正在處理的陣列
•thisArg:這是一個可選參數,當執行回呼的時候它作為回呼函數的this
範例:
var myarray = [1, 2, 3, 4] words = 'hello 123 world how 345 ya doing'.split(' '); re = '[a-zA-Z]'; // 筛选整数 console.log([-2, -1, 0, 1, 2].filter(function(x) { return x > 0 })); // 筛选所有含字母的单词 console.log(words.filter(function(s) { return s.match(re); })); // 随机移除数组中的元素 console.log(myarray.filter(function() { return Math.floor(Math.random() * 2) }));
Array.prototype.reduce()
reduce()函数,有时也称为fold,它用于把数组中的所有值聚集到一起。回调需要返回组合对象的逻辑。 对于数字来说,它们往往会被加到一起或者乘到一起。对于字符串来说,它们往往是被追加到一起。
语法:arr.reduce(callback [, initialValue]);
参数
•callback():此函数把两个对象合并成一个对象,并将其返回。参数有: ◦previousValue:上一次回调函数被调用时返回的值,或者是初始值(如果有的话)
◦currentValue:数组当前正在处理的元素
◦index:数组中当前元素的序数
◦array:当前正在处理的数组
•initialValue:可选。第一次回调所传入参数的初始值
例子
var numbers = [1, 2, 3, 4]; // 把数组中所有的值加起来 console.log([1, 2, 3, 4, 5].reduce(function(x, y) { return x + y }, 0)); // 查找数组中最大的值 console.log(numbers.reduce(function(a, b) { return Math.max(a, b) // max()函数只能有两个参数 }) );
其它函数
map()、filter()和reduce()函数在我们辅助函数的工具箱里并不孤单。这里还有更多的函数几乎在所有函数式应用里都会被使用。
Array.prototype.forEach
forEach()函数本质上是map()函数的非纯版本,它会遍历整个数组,并对每个元素应用回调。 然而这些回调函数不返回值。它是实现for循环的一个更纯粹的方式。
语法:arr.forEach(callback [, thisArg]);
参数:
•callback():对数组中每一个元素所应用的。参数有: ◦currentValue:数组中当前正在处理的元素
◦index:数组中当前元素的序数
◦array:正在处理的数组
•thisArg:可选。回调函数中作为this的值
例子:
var arr = [1, 2, 3]; var nodes = arr.map(function(x) { var elem = document.createElement("div"); elem.textContent = x; return elem; }); // 对每一个元素的值输出日志 arr.forEach(function(x) { console.log(x) }); // 把节点追加到DOM上 nodes.forEach(function(x) { document.body.appendChild(x) });
Array.prototype.concat
如果不用for或while处理数组,你会经常需要把数组拼接起来。另一个Javascript内建函数concat就是专门干这事儿的。 concat函数会返回一个新数组但不改变旧数组。它可以把你传入的所有参数拼接到一起。
console.log([1, 2, 3].concat(['a','b','c']) // 拼接两个数组
// Output: [1, 2, 3, 'a','b','c']
它返回两个数组拼接成的数组,同时原来的那些数组没有被改变。这就意味着concat函数可以链式调用。
var arr1 = [1,2,3]; var arr2 = [4,5,6]; var arr3 = [7,8,9]; var x = arr1.concat(arr2, arr3); var y = arr1.concat(arr2).concat(arr3)); var z = arr1.concat(arr2.concat(arr3))); console.log(x); console.log(y); console.log(z);
变量x、y、z的值最后都是[1,2,3,4,5,6,7,8,9]。
Array.prototype.reverse
这个Javascript内建函数是用于数组变形的。reverse函数用于将一个数组反转,也就是第个一元素会跑到最后, 而最后一个元素变成了第一个元素。
然而,这个函数并不会返回一个新的数组,而是把原来的数组替换掉了。我们可以做个更好的。下面是一个纯的反转数组函数
var invert = function(arr) { return arr.map(function(x, i, a) { return a[a.length - (i + 1)]; }); }; var q = invert([1, 2, 3, 4]); console.log(q);
Array.prototype.sort
与map()、filter()和reduce()函数相似,排序函数sort()需要传入一个回调函数来定义数组如何排序。 但是,跟reverse()一样,它也会把原来的数组替换。这可不太好。
arr = [200, 12, 56, 7, 344];
console.log(arr.sort(function(a,b){return a–b}) );
// arr现在是: [7, 12, 56, 200, 344];
我们可以写一个纯函数的sort(),但是排序算法的源代码很麻烦。对于特别大的数组,应当根据特定的数据结构来选用适合的算法, 比如快速排序、合并排序、冒泡排序等等。
Array.prototype.every 和 Array.prototype.some
Array.prototype.every() 和 Array.prototype.some() 都是纯的高阶函数,它们是Array对象的方法, 通过回调函数根据数组各元素返回的布尔值(或相当于布尔的值)来进行测试。如果数组中所有的元素通过回调函数计算都返回True, every()函数就返回true;如果数组中有一个元素返回True,some()函数就返回True。
例子:
function isNumber(n) { return !isNaN(parseFloat(n)) && isFinite(n); } console.log([1, 2, 3, 4].every(isNumber)); // Return: true console.log([1, 2, 'a'].every(isNumber)); // Return: false console.log([1, 2, 'a'].some(isNumber)); // Return: true

是的,JavaScript的引擎核心是用C語言編寫的。 1)C語言提供了高效性能和底層控制,適合JavaScript引擎的開發。 2)以V8引擎為例,其核心用C 編寫,結合了C的效率和麵向對象特性。 3)JavaScript引擎的工作原理包括解析、編譯和執行,C語言在這些過程中發揮關鍵作用。

JavaScript是現代網站的核心,因為它增強了網頁的交互性和動態性。 1)它允許在不刷新頁面的情況下改變內容,2)通過DOMAPI操作網頁,3)支持複雜的交互效果如動畫和拖放,4)優化性能和最佳實踐提高用戶體驗。

C 和JavaScript通過WebAssembly實現互操作性。 1)C 代碼編譯成WebAssembly模塊,引入到JavaScript環境中,增強計算能力。 2)在遊戲開發中,C 處理物理引擎和圖形渲染,JavaScript負責遊戲邏輯和用戶界面。

JavaScript在網站、移動應用、桌面應用和服務器端編程中均有廣泛應用。 1)在網站開發中,JavaScript與HTML、CSS一起操作DOM,實現動態效果,並支持如jQuery、React等框架。 2)通過ReactNative和Ionic,JavaScript用於開發跨平台移動應用。 3)Electron框架使JavaScript能構建桌面應用。 4)Node.js讓JavaScript在服務器端運行,支持高並發請求。

Python更適合數據科學和自動化,JavaScript更適合前端和全棧開發。 1.Python在數據科學和機器學習中表現出色,使用NumPy、Pandas等庫進行數據處理和建模。 2.Python在自動化和腳本編寫方面簡潔高效。 3.JavaScript在前端開發中不可或缺,用於構建動態網頁和單頁面應用。 4.JavaScript通過Node.js在後端開發中發揮作用,支持全棧開發。

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。1)C 用于解析JavaScript源码并生成抽象语法树。2)C 负责生成和执行字节码。3)C 实现JIT编译器,在运行时优化和编译热点代码,显著提高JavaScript的执行效率。

JavaScript在現實世界中的應用包括前端和後端開發。 1)通過構建TODO列表應用展示前端應用,涉及DOM操作和事件處理。 2)通過Node.js和Express構建RESTfulAPI展示後端應用。

JavaScript在Web開發中的主要用途包括客戶端交互、表單驗證和異步通信。 1)通過DOM操作實現動態內容更新和用戶交互;2)在用戶提交數據前進行客戶端驗證,提高用戶體驗;3)通過AJAX技術實現與服務器的無刷新通信。


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

SecLists
SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

SublimeText3漢化版
中文版,非常好用

MantisBT
Mantis是一個易於部署的基於Web的缺陷追蹤工具,用於幫助產品缺陷追蹤。它需要PHP、MySQL和一個Web伺服器。請查看我們的演示和託管服務。

Atom編輯器mac版下載
最受歡迎的的開源編輯器