數(shù)組是有reduce
函數(shù)的护昧,求和之類的很方便。一些類數(shù)組對象粗截,比如{score1 : 100, score2 : 90, score3 : 95 }
惋耙,不能用reduce
函數(shù)函數(shù),不是很方便慈格。所以考慮提供一個reduce
全局函數(shù)怠晴。
實現(xiàn)的思路很簡單,就是將對象的屬性遍歷出來浴捆,組成一個數(shù)組蒜田,那么就可以方便地使用reduce
函數(shù)了
數(shù)組的reduce函數(shù)
reduce()
方法對累加器和數(shù)組中的每個元素 (從左到右)應(yīng)用一個函數(shù),將其減少為單個值选泻。一次作用數(shù)組的每一個值冲粤,最后返回一個單一值。最經(jīng)典的例子是累加求和页眯。不過實際的應(yīng)用很廣泛梯捕,比如可以拼接字符串,求最大值等等窝撵。
如果函數(shù)參數(shù)不是一個函數(shù)的話傀顾,會出錯。函數(shù)參數(shù)是必選參數(shù)碌奉。
這個變換函數(shù)本身最多提供
4
個參數(shù)短曾,依次是accumulator寒砖,currentValue,currentIndex嫉拐,array
哩都。一般情況下,給2
個參數(shù)婉徘,accumulator漠嵌,currentValue
。初始值
initialValue
是一個可選參數(shù)盖呼。在實際使用中儒鹿,大多數(shù)情況下是需要提供的。提供合適的初始值几晤,需要考慮一下挺身。一般情況是0
,或者空數(shù)組[]
锌仅,空字符串''
等等章钾。一般提倡給初始值
initialValue
,變換函數(shù)的參數(shù)accumulator
一開始就是這個initialValue
热芹,然后依次參與迭代運算贱傀,思路比較順。accumulator
和initialValue
伊脓,還有最終結(jié)果是相同的類型如果不給初始值
initialValue
府寒,那么accumulator
一開始是數(shù)組的第1個值,currentValue
一開始是數(shù)組的第2
個值报腔。這樣株搔,會導(dǎo)致迭代變換次數(shù)比數(shù)組的元素個數(shù)少1
,理解上不是很方便纯蛾。
一般情況纤房,給初始值initialValue
,并且注意其格式翻诉,這個決定了最終結(jié)果的格式最后的結(jié)果炮姨,和初始值
initialValue
的形式是一樣的。所以期望什么樣的結(jié)果碰煌,就給什么格式的初始值initialValue
舒岸,這個要注意。變換函數(shù)的array參數(shù)就是調(diào)用reduce函數(shù)的這個數(shù)組芦圾,可以改變蛾派,不過強烈建議不要改變數(shù)組。后面兩個參數(shù)
currentIndex,array
洪乍,如果不是必須梭依,一般不要列出來。
JavaScript數(shù)組的高級用法-reduce和reduceRight詳解
對象屬性的遍歷
for...in
返回的是可枚舉的屬性典尾,包括自己的屬性以及原型鏈上的屬性。按照類的說法糊探,也就是說會把父類的屬性也枚舉出來钾埂。for...in
如果要過濾掉父類的屬性,也就是原型鏈上的屬性忽略掉科平,那么要借助Object
的hasOwnProperty
屬性進(jìn)行判斷和過濾Object.keys()
相當(dāng)于for...in + hasOwnProperty
效果褥紫。只枚舉自己的可枚舉屬性,不管父類的屬性瞪慧。Object.getOwnPropertyNames()
只列舉自己的屬性髓考,不會管父類的屬性。不過弃酌,會列出所有的屬性氨菇,不管這個屬性標(biāo)記為可枚舉還是不可枚舉。比如妓湘,數(shù)組對象查蓉,會把length
屬性也列舉出來。這幾個函數(shù)最好用于
Object
類型榜贴,不要用于數(shù)組豌研。對于數(shù)組,返回的是字符串的0,1,2,3 ...
唬党,沒什么實際意義鹃共。
JavaScript中in操作符(for..in)、Object.keys()和Object.getOwnPropertyNames()的區(qū)別
reduce全局函數(shù)
- 導(dǎo)出單一函數(shù)的方式驶拱,方便使用霜浴。文件名
reduce_function.js
// 全局函數(shù),區(qū)別于數(shù)組的reduce()方法
module.exports = function reduceFunction(callback, initialValue, target) {
// 如果f不是函數(shù)蓝纲,調(diào)用數(shù)組的reduce會報錯
if ('function' !== typeFunction(callback)) {
return target;
}
const type = typeFunction(target)
if (type === 'array') {
return '_' === initialValue // 判斷是否調(diào)用init參數(shù)
? target.reduce(callback)
: target.reduce(callback, initialValue);
} else if (type === 'object') {
// ES7 , chrome瀏覽器已經(jīng)可以用
// const values = Object.values(target);
const keys = Object.keys(target);
const values = keys.map(function (key) {
return target[key];
})
return '_' === initialValue // 判斷是否調(diào)用init參數(shù)
? values.reduce(callback)
: values.reduce(callback, initialValue);
} else {
return target;
}
}
// private
function typeFunction(object) {
return Object.prototype.toString.call(object).slice(8, -1).toLowerCase();
}
- 測試代碼坷随,在同一目錄下,文件名
reduce_function_test.js
const reduceFunction = require('./reduce_function.js');
const log = console.log;
// 數(shù)組累加
const items = [10, 120, 1000];
const add = function(previous, current) {
return previous + current;
};
const max = function(previous, current) {
return previous > current
? previous
: current;
};
const multiply = function(previous, current) {
return previous * current;
};
const append = function(previous, current) {
return previous + '::' + current;
};
log(items.reduce(add, 0)); // 1130
log(items.reduce(max, 0)); // 1000
log(items.reduce(multiply, 1)); // 1200000
log(items.reduce(append)); // '10::120::1000'
log(reduceFunction(add, 0, items)); // 1130
log(reduceFunction(max, 0, items)); // 1000
log(reduceFunction(multiply, 1, items)); // 1200000
log(reduceFunction(append, '_', items)); // '10::120::1000'
// 對象屬性累加
const scores = {
score1 : 10,
score2 : 120,
score3 : 1000,
}
log(reduceFunction(add, 0, scores)); // 1130
log(reduceFunction(max, 0, scores)); // 1000
log(reduceFunction(multiply, 1, scores)); // 1200000
log(reduceFunction(append, '_', scores)); // '10::120::1000'
// 數(shù)組轉(zhuǎn)數(shù)字的例子驻龟,比如[1,6,8,8,8] => 16888
function addDigitValue(previousValue, currentDigit, currentIndex, array) {
const exponent = (array.length - 1) - currentIndex;
const digitValue = currentDigit * Math.pow(10, exponent);
return previousValue + digitValue;
}
log([1,6,8,8,8].reduce(addDigitValue, 0)); // 16888
log(reduceFunction(addDigitValue, 0, {
萬 : 168,
千 : 6,
百 : 8,
十 : 8,
個 : 8,
})); // 1686888