Javascript不清不楚之reduce
程序员文章站
2023-12-25 10:34:45
...
reduce
下面这段代码实现来自:MDN - reduce
// Production steps of ECMA-262, Edition 5, 15.4.4.21
// Reference: http://es5.github.io/#x15.4.4.21
// https://tc39.github.io/ecma262/#sec-array.prototype.reduce
if (!Array.prototype.reduce) {
Object.defineProperty(Array.prototype, 'reduce', {
//callback累加回调函数,initialValue累加初始和
value: function(callback /*, initialValue*/) {
if (this === null) {
throw new TypeError( 'Array.prototype.reduce ' +
'called on null or undefined' );
}
if (typeof callback !== 'function') {
throw new TypeError( callback +
' is not a function');
}
// 1. Let O be ? ToObject(this value).
var o = Object(this);
// 2. Let len be ? ToLength(? Get(O, "length"))(无符号右移)
var len = o.length >>> 0;
// Steps 3, 4, 5, 6, 7
var k = 0;
var value;
if (arguments.length >= 2) {
//如果传入了初始累计和,则将其赋值给value,这时候循环次数和数组的长度相同
value = arguments[1];
} else {
//如果没有传入初始累计和,则调整开始执行回调函数的索引,找到第一个索引值
while (k < len && !(k in o)) {
k++;
}
// 3. If len is 0 and initialValue is not present,
// throw a TypeError exception(空数组进行reduce操作会报错)
if (k >= len) {
throw new TypeError( 'Reduce of empty array ' +
'with no initial value' );
}
value = o[k++];
}
// 8. Repeat, while k < len
while (k < len) {
// a. Let Pk be ! ToString(k).
// b. Let kPresent be ? HasProperty(O, Pk).
// c. If kPresent is true, then
// i. Let kValue be ? Get(O, Pk).
// ii. Let accumulator be ? Call(
// callbackfn, undefined,
// « accumulator, kValue, k, O »).
if (k in o) {
// 调用回调函数,参数依次为(累计和,当前值,当前索引,数组),回调函数需要返回一个累计和
value = callback(value, o[k], k, o);
}
// d. Increase k by 1.
k++;
}
// 9. Return accumulator.
return value;
}
});
}
数组累计和
var sum = [0, 1, 2, 3].reduce(function (a, b) {
return a + b;
}, 0);
// sum is 6
// 等价于下面这种计算,区别是上面的回调函数会执行4次,下面的回调函数会执行3次
var sum = [0, 1, 2, 3].reduce(function (a, b) {
return a + b;
});
将二维数组转换为一维数组
var flattened = [[0, 1], [2, 3], [4, 5]].reduce(
(a, b) => [...a, ...b]
);
// flattened = [0, 1, 2, 3, 4, 5]
// 记一次面试经历:将[{a:1}, {b:2}, {c:3}]类型的数组转换为[a,b,c,1,2,3]
[{a:1}, {b:2}, {c:3}].reduce((res, item, index) => {
for(var key in item){
res.splice(index, 0, key);
res.push(item[key]);
}
return res;
}, []);
数组去重
[5,4,3,2,1,1,2,2,3,4,5,6].reduce((res, value, index) => {
if(!res.includes(value)){
res.push(value);
}
return res;
}, []);
// [5, 4, 3, 2, 1, 6] 没有改变非重复元素的排列顺序
[5,4,3,2,1,1,2,2,3,4,5,6].sort().reduce((res, value, index) => {
if(res.length === 0 || res[res.length - 1] !== value){
res.push(value);
}
return res;
}, []);
// [1, 2, 3, 4, 5, 6] 改变了元素的排列顺序
统计数组中元素重复次数
[5,4,3,2,1,1,2,2,3,4,5,6].reduce((res, value, index) => {
if(!(value in res)){
res[value] = 1;
}else{
++res[value];
}
return res;
}, {});
// {1: 2, 2: 3, 3: 2, 4: 2, 5: 2, 6: 1}
推荐阅读
-
Js之软键盘实现(js源码)_javascript技巧
-
Javascript不清不楚之reduce
-
Javascript不清不楚之concat
-
JavaScript入门之对象与JSON详解_基础知识
-
Javascript新手入门之字符串拼接与变量的应用
-
JS基础之undefined与null的区别分析_javascript技巧
-
zTree插件之单选下拉菜单实例代码_javascript技巧
-
JavaScript 定时器 SetTimeout之定时刷新窗口和关闭窗口(代码超简单)_javascript技巧
-
javascript dom操作之cloneNode文本节点克隆使用技巧_javascript技巧
-
前端笔记之JavaScript面向对象(四)组件化开发&轮播图|俄罗斯方块实战