欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

javascript函數(shù)式編程程序員的工具集

 更新時間:2015年10月11日 11:29:19   投稿:hebedich  
函數(shù)式編程語言一向被認(rèn)為是比其它編程語言更高深的語言。一是因為函數(shù)式編程語言的語法很另類,比如Lisp語言,二是因為函數(shù)式編程語言都很古老,比如Schema語言。在如今面向?qū)ο笳Z言大行其道的時代,函數(shù)式編程語言有其特殊的優(yōu)勢

如果你仔細(xì)看了到目前為止出現(xiàn)過的示例代碼,你會發(fā)現(xiàn)這里面的一些方法不太熟悉。 它們是map()、filter()和reduce()函數(shù),它們對任何語言的函數(shù)式編程都至關(guān)重要。 它們可以讓你不必使用循環(huán)和語句,寫出更簡潔的代碼。

map()、filter()和reduce()函數(shù)組成了函數(shù)式程序員工具集的核心部分,這個工具集包括一系列純的、 高階的函數(shù),它們是函數(shù)式方法的主力。實際上,它們是純函數(shù)和高階函數(shù)的典型,它們以一個函數(shù)為輸入, 返回一個輸出結(jié)果,并且不產(chǎn)生副作用。

然而它們是瀏覽器中ECMAScript 5.1的實現(xiàn)標(biāo)準(zhǔn),它們只工作于數(shù)組。每次調(diào)用它們,一個新的數(shù)組會被創(chuàng)建并返回, 而原來存在的那個數(shù)組不會被改變。它們以函數(shù)為輸入,經(jīng)常使用匿名函數(shù)作為回調(diào)函數(shù)。它們遍歷數(shù)組, 并對數(shù)組的每一個元素應(yīng)用這個函數(shù)!

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]

還有一點,它們只作用于數(shù)組,無法作用于其它可迭代的數(shù)據(jù)結(jié)構(gòu),比如對象。不用擔(dān)心, 有很多庫比如Underscore.js,Lazy.js,stream.js等等都實現(xiàn)了它們自己的更強大的map()、 filter()和reduce()。

回調(diào)

如果你以前從來沒用過回調(diào),那這個概念可能會讓你有些迷惑。尤其是在Javascript中, Javascript給出了好幾種聲明函數(shù)的方式。

回調(diào)函數(shù)用于傳遞給另外一個函數(shù)供它們使用,這是一種像傳遞對象一樣來傳遞邏輯的方式:

var myArray = [1,2,3];
function myCallback(x){return x+1};
console.log(myArray.map(myCallback));



對于比較簡單的任務(wù)可以用匿名函數(shù):

console.log(myArray.map(function(x){return x+1}));

回調(diào)不僅用于函數(shù)式編程,在Javascript中它們能干很多事情。僅作為例子,這有個callback()函數(shù)用于jQuery的AJAX調(diào)用:

function myCallback(xhr) {
 console.log(xhr.status);
 return true;
}
$.ajax(myURI).done(myCallback);

注意這里只用了函數(shù)的名字,因為我們并不是要調(diào)用函數(shù)而是傳遞函數(shù),寫成這樣就錯了:

$.ajax(myURI).fail(myCallback(xhr)); 
// 或者
$.ajax(myURI).fail(myCallback());

如果我們調(diào)用了函數(shù)會發(fā)生什么?在這個例子里,myCallback(xhr)會嘗試執(zhí)行,控制臺將打印“undefined”, 并會返回true。當(dāng)ajax()完成調(diào)用時,它根據(jù)名字找到的回調(diào)函數(shù)將是一個"true",然后就報錯了。

也就是說我們無法指定給回調(diào)函數(shù)傳什么參數(shù),如果我們的回調(diào)函數(shù)需要讓ajax()函數(shù)傳給他我們想要的參數(shù), 我們可以把回到函數(shù)包在一個匿名函數(shù)里:

function myCallback(status) {
 console.log(status);
 return true;
}
$.ajax(myURI).done(function(xhr) {
 myCallback(xhr.status)
});

Array.prototype.map()

map()是這些函數(shù)的老大,它簡單地對數(shù)組里的元素依此應(yīng)用回調(diào)函數(shù)。

語法:arr.map(callback [, thisArg]);

參數(shù):
•callback(): 這個函數(shù)為新數(shù)組產(chǎn)生一個元素,它接收的參數(shù): ◦currentValue:數(shù)組當(dāng)前遍歷到的元素
◦index:數(shù)組中當(dāng)前元素序數(shù)
◦array:當(dāng)前正在處理的數(shù)組

•thisArg:這是個可選參數(shù),當(dāng)執(zhí)行回調(diào)的時候它作為回調(diào)函數(shù)的this

例子:

var
 integers = [1, -0, 9, -8, 3],
 numbers = [1, 2, 3, 4],
 str = 'hello world how ya doing?';
 
// 將整數(shù)映射為他們自己的絕對值
console.log(integers.map(Math.abs));

// 將數(shù)組中的元素與自己的位置序數(shù)相乘
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中數(shù)組對象的標(biāo)準(zhǔn)方法,你也可以很容易地擴展自己的對象。

MyObject.prototype.map = function(f) {
  return new MyObject(f(this.value));
 }; 

Array.prototype.filter()

filter()函數(shù)用于把數(shù)組中的一些元素篩選出來?;卣{(diào)函數(shù)必須返回真(保留到新數(shù)組里)或假(扔掉)。 用map()可以做類似的事情,就是把你像扔掉的元素返回為null,不過filter()函數(shù)會在新數(shù)組里面刪除這些不要的元素, 而不是留個null占著位置。

語法:arr.filter(callback [, thisArg]);

•callback():這個函數(shù)用來測試數(shù)組中的每個元素,要保留返回真,否則返回假。它有這些參數(shù): ◦currentValue:數(shù)組當(dāng)前遍歷到的元素
◦index:數(shù)組中當(dāng)前元素的序數(shù)
◦array:當(dāng)前正在處理的數(shù)組

•thisArg:這是個可選參數(shù),當(dāng)執(zhí)行回調(diào)的時候它作為回調(diào)函數(shù)的this

例子:

var myarray = [1, 2, 3, 4]
words = 'hello 123 world how 345 ya doing'.split(' ');
re = '[a-zA-Z]';
// 篩選整數(shù)
console.log([-2, -1, 0, 1, 2].filter(function(x) {
 return x > 0
}));
// 篩選所有含字母的單詞
console.log(words.filter(function(s) {
 return s.match(re);
}));
// 隨機移除數(shù)組中的元素
console.log(myarray.filter(function() {
 return Math.floor(Math.random() * 2)
}));

Array.prototype.reduce()

reduce()函數(shù),有時也稱為fold,它用于把數(shù)組中的所有值聚集到一起?;卣{(diào)需要返回組合對象的邏輯。 對于數(shù)字來說,它們往往會被加到一起或者乘到一起。對于字符串來說,它們往往是被追加到一起。

語法:arr.reduce(callback [, initialValue]);

參數(shù)
•callback():此函數(shù)把兩個對象合并成一個對象,并將其返回。參數(shù)有: ◦previousValue:上一次回調(diào)函數(shù)被調(diào)用時返回的值,或者是初始值(如果有的話)
◦currentValue:數(shù)組當(dāng)前正在處理的元素
◦index:數(shù)組中當(dāng)前元素的序數(shù)
◦array:當(dāng)前正在處理的數(shù)組

•initialValue:可選。第一次回調(diào)所傳入?yún)?shù)的初始值

例子

var numbers = [1, 2, 3, 4];

// 把數(shù)組中所有的值加起來
console.log([1, 2, 3, 4, 5].reduce(function(x, y) {
 return x + y
}, 0));

// 查找數(shù)組中最大的值
console.log(numbers.reduce(function(a, b) {
  return Math.max(a, b) // max()函數(shù)只能有兩個參數(shù)
 }) 
);

其它函數(shù)

map()、filter()和reduce()函數(shù)在我們輔助函數(shù)的工具箱里并不孤單。這里還有更多的函數(shù)幾乎在所有函數(shù)式應(yīng)用里都會被使用。

Array.prototype.forEach

forEach()函數(shù)本質(zhì)上是map()函數(shù)的非純版本,它會遍歷整個數(shù)組,并對每個元素應(yīng)用回調(diào)。 然而這些回調(diào)函數(shù)不返回值。它是實現(xiàn)for循環(huán)的一個更純粹的方式。

語法:arr.forEach(callback [, thisArg]);

參數(shù):
•callback():對數(shù)組中每一個元素所應(yīng)用的。參數(shù)有: ◦currentValue:數(shù)組中當(dāng)前正在處理的元素
◦index:數(shù)組中當(dāng)前元素的序數(shù)
◦array:正在處理的數(shù)組

•thisArg:可選?;卣{(diào)函數(shù)中作為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)
});

// 把節(jié)點追加到DOM上
nodes.forEach(function(x) {
 document.body.appendChild(x)
});

Array.prototype.concat

如果不用for或while處理數(shù)組,你會經(jīng)常需要把數(shù)組拼接起來。另一個Javascript內(nèi)建函數(shù)concat就是專門干這事兒的。 concat函數(shù)會返回一個新數(shù)組但不改變舊數(shù)組。它可以把你傳入的所有參數(shù)拼接到一起。
console.log([1, 2, 3].concat(['a','b','c']) // 拼接兩個數(shù)組
// Output: [1, 2, 3, 'a','b','c']

它返回兩個數(shù)組拼接成的數(shù)組,同時原來的那些數(shù)組沒有被改變。這就意味著concat函數(shù)可以鏈?zhǔn)秸{(diào)用。

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內(nèi)建函數(shù)是用于數(shù)組變形的。reverse函數(shù)用于將一個數(shù)組反轉(zhuǎn),也就是第個一元素會跑到最后, 而最后一個元素變成了第一個元素。

然而,這個函數(shù)并不會返回一個新的數(shù)組,而是把原來的數(shù)組替換掉了。我們可以做個更好的。下面是一個純的反轉(zhuǎn)數(shù)組函數(shù)

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()函數(shù)相似,排序函數(shù)sort()需要傳入一個回調(diào)函數(shù)來定義數(shù)組如何排序。 但是,跟reverse()一樣,它也會把原來的數(shù)組替換。這可不太好。
arr = [200, 12, 56, 7, 344];
console.log(arr.sort(function(a,b){return a–b}) );
// arr現(xiàn)在是: [7, 12, 56, 200, 344];

我們可以寫一個純函數(shù)的sort(),但是排序算法的源代碼很麻煩。對于特別大的數(shù)組,應(yīng)當(dāng)根據(jù)特定的數(shù)據(jù)結(jié)構(gòu)來選用適合的算法, 比如快速排序、合并排序、冒泡排序等等。

Array.prototype.every 和 Array.prototype.some

Array.prototype.every() 和 Array.prototype.some() 都是純的高階函數(shù),它們是Array對象的方法, 通過回調(diào)函數(shù)根據(jù)數(shù)組各元素返回的布爾值(或相當(dāng)于布爾的值)來進(jìn)行測試。如果數(shù)組中所有的元素通過回調(diào)函數(shù)計算都返回True, every()函數(shù)就返回true;如果數(shù)組中有一個元素返回True,some()函數(shù)就返回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

相關(guān)文章

最新評論