数组在工作中使用频繁,但我们大多数情况下只使用到了部分特性,久而久之,对于数组其它的相关特性就变得模糊起来,不免有错漏不全的理解,这里花了一点时间,对最常用的数组做一些总结。http://coderlt.coding.me/2016/09/23/JS-Array/#more
定义
数组的标准定义:一个存储元素的线性集合,元素可以通过索引来任意存取,索引通常是数字,用来计算元素之间存储位置的偏移量。
数组(array)是按次序排列的一组值。每个值的位置都有编号(从0开始),整个数组用方括号表示。
内置方法
- concat / slice / splice
- sort / reverse
- push / unshift
- pop / shift
- toString
- join
从已有的数组创建新的数组
concat / slice / splice
concat
合并两个或多个数组,返回合并结果
不改变原有数组,返回一个新的合并数组
arrayObject.concat(arrayX,arrayX,......,arrayX)
,
arrayX
可以是值/数组对象
[
1,
2].concat(
3,
4);
[
1,
2].concat([
3],[
4,
5],[
6]);
[
1].concat([
2,
3]);
[
1,
2].concat(
3);
|
slice
从现有的数组返回选定的元素组成的数组 不改变原有数组
arrayObject.slice(start,end)
start 和 end 定义了选取范围,正数从0开始,负数从-1开始,始终为左闭右开,也就是左边包含右边不包含
[
1,
2,
3,
4].slice(
0,
1);
[
1,
2,
3,
4].slice(
1,
3);
[
1,
2,
3,
4].slice(
-1);
[
1,
2,
3,
4].slice(
-2);
[
1,
2,
3,
4].slice(
-2,
-1);
|
splice
方法向/从数组中添加/删除项目,然后返回被删除的项目组成的新数组 会改变原有数组
arrayObject.splice(index,howmany,items,...)
index 起始位置,可以是负数
howmany 要删除的个数,0为不删除
items 要添加的元素
var arr1 = [
1,
2,
3,
4];
var arr2 = arr1.slice();
var arr3 = arr1.slice();
var removed = arr1.splice(
1,
1);
console.log(removed);
console.log(arr1);
var replace = arr2.splice(
2,
1,
5);
console.log(replace);
console.log(arr2);
var insert = arr3.splice(
3,
0,
5,
6,
7);
console.log(insert);
console.log(arr3);
|
数组排序
sort / reverse
sort
用于对数组的元素进行排序
将对原数组操作,会改变原数组
arrayObject.sort(sortFn)
sortFn 为函数,用于提供排序比较规则,返回值是正值,则第一个参数比第二个大,负值,则第1个比第2个小,零,则两个数相等
如果sortFn为空,则按照字符编码的顺序进行排序
[
1,
51,
4,
12,
2,
3].sort()
[
1,
51,
4,
12,
2,
3].sort(
function(a,b){
return a-b})
[
1,
51,
4,
12,
2,
3].sort(
function(a,b){
return b-a})
[
1,
51,
4,
12,
2,
3].sort(
new
Function(
'a',
'b',
'return a-b'))
[
1,
51,
4,
12,
2,
3].sort(
(a,b)=>a-b)
|
reverse
用于颠倒数组中元素的顺序 会改变原有的数组
[
1,
3,
4,
5].reverse()
'54321'.split(
'').reverse().join(
'');
Number(
Number(
12345).toString().split(
'').reverse().join(
''))
|
为数组增减元素
- push 添加 元素至数组尾部,返回新的数组长度
- unshift 添加 元素至数组开头,返回新的数组长度
- pop 删除 尾部元素,返回删除的元素
- shift 删除 头部元素,返回删除的元素
都是直接对原数组操作,会改变原有数组
var arr = [
1,
2,
3,
4];
var arr1 = arr.slice();
var arr2 = arr.slice();
var arr3 = arr.slice();
var arr4 = arr.slice();
console.log(arr1.push(
5), arr1);
console.log(arr2.unshift(
0), arr2);
console.log(arr3.pop(), arr3);
console.log(arr4.shift(), arr4);
|
数组转字符串
toString / join
[
1,
2,
3,
4].toString()
[
1,
2,
3,
4]+
''
[
1,
2,
3,
4].join(
'-');
|
ES5新增
- Array.isArray()
- [].indexOf() / [].lastIndexOf()
- [].forEach / [].map()
- [].every() / [].some()
- [].filter()
- [].reduce() / [].reduceRight()
数组类型判断
自定义一个方法来判断是否为数组
function isArray(obj){
return
Object.prototype.toString.call(obj) ===
'[object Array]';
}
isArray([]);
|
ES5新增 Array.isArray()
来判断是否为数组
Array.isArray([]);
Array.isArray({
a:
1});
if(
typeof
Array.isArray !==
'function'){
Array.isArray =
function(obj){
return
Object.prototype.toString.call(obj) ===
'[object Array]';
}
}
|
查找元素
indexOf(el, startIndex) / lastIndexOf(el, lastIndex)
没有查找到元素返回-1,查找到元素,返回查找到的第一个的索引值,lastIndexOf
为从后面查起
- startIndex 表示从哪个索引开始找,默认为第1个索引
- lastIndex 表示从倒数第几个索引开始找,默认为最后一个索引
[
1,
2,
3,
2,
4].indexOf(
2);
[
1,
2,
3,
2,
4].indexOf(
2,
2);
[
1,
2,
3,
2,
4].lastIndexOf(
2);
[
1,
2,
3,
2,
4].indexOf(
5);
[
1,
'1'].indexOf(
'1');
[
1,
NaN].indexOf(
NaN);
[
1,{}].indexOf({});
if(
Array.prototype.indexOf !==
'function'){
Array.prototype.indexOf =
function(searchEl, startIndex){
var index =
-1;
startIndex = startIndex *
1 ||
0;
for (
var k =
0, len =
this.length; k < len; k++) {
if (k >= startIndex &&
this[k] === searchEl) {
index = k;
break;
}
}
return index;
}
}
if(
Array.prototype.lastIndexOf !==
'function'){
Array.prototype.lastIndexOf =
function(searchEl, lastIndex){
var index =
-1, len =
this.length;
lastIndex = lastIndex *
1 || len;
while (len--) {
if (len <= lastIndex &&
this[len] === searchEl) {
index = len;
break;
}
}
return index;
}
}
|
数据遍历
[].forEach() / [].map()
[].forEach(function(value, index, arr){}, context)
循环遍历数组中的每一个元素,处理函数中的参数依次为:当前元素、当前元素索引、原数组
forEach的第二个参数,可以指定处理函数中this的指向
var arr = [
1,
2,
3];
arr.forEach(
function(v,i,a){
console.log(v,i,a);
v+=
1;
})
console.log(arr);
for(
var i=
0; i<arr.length; i++){
console.log(arr[i], i, arr);
}
if(
Array.prototype.forEach !==
'function'){
Array.prototype.forEach =
function(fn, context){
for(
var i=
0, len=
this.length; i<len; i++){
if(
typeof fn ===
'function' &&
Object.prototype.hasOwnProperty.call(
this, i)){
fn.call(context,
this[i], i,
this);
}
}
}
}
|
jQuery中的 $.each(function(index, values, arr){})
回调中的参数第1个是索引,第2个是元素,$.map()
亦是如此
map(function(value, index, arr){})
与forEach类似,返回一个新的数组,不改变原有数组
var arr = [
1,
2,
3];
var res = arr.map(
function(v){
return v+
1;
});
console.log(arr);
console.log(res);
if(
Array.prototype.map !==
'function'){
Array.prototype.map =
function(fn, context){
var res = [];
if(
typeof fn ===
'function'){
for(
var i=
0, len=
this.length; i<len; i++){
res.push(fn.call(context,
this[i], i,
this));
}
}
return res;
}
}
|
map的回调处理函数一定要有返回值,如果没用,则会返回undefined
检测是否包含某元素
[].every(function(value, index, arr){}, context) / [].some(function(value, index, arr){}, context)
- 数组元素的逻辑判定,回调函数返回true/false
- some是所判定的元素只要数组中有一个符合条件就返回true
- ervery是数组中必须所有元素都符合条件就返回true,否则返回false
- 在空数组上调用every返回true,some返回false
console.log([
1,
2,
3,
4].some(
v=>v>
3))
console.log([
1,
2,
3,
4].every(
v=>v>
3))
console.log([].every(
v=>v>
3))
console.log([].some(
v=>v>
3))
if(
Array.prototype.some !==
'function'){
Array.prototype.some =
function(fn, context){
var passed =
false;
if (
typeof fn ===
"function") {
for (
var k =
0, length =
this.length; k < length; k++) {
if (passed ===
true)
break;
passed = !!fn.call(context,
this[k], k,
this);
}
}
return passed;
}
}
if (
typeof
Array.prototype.every !=
"function") {
Array.prototype.every =
function (fn, context) {
var passed =
true;
if (
typeof fn ===
"function") {
for (
var k =
0, length =
this.length; k < length; k++) {
if (passed ===
false)
break;
passed = !!fn.call(context,
this[k], k,
this);
}
}
return passed;
};
}
|
数组过滤
[].filter(fn, context)
- 当遍历元素时,fn返回true,则返回这个元素,否则不返回,fn中返回值只要弱等于true或false即可,使用==比较
- filter返回一个新的结果数组,不改变原有数组
[
1,
2,
3,
4].filter(
v=>v>
2);
[
1,
2,
0,
null,
''].filter(
v=>v);
if(
Array.prototype.some !==
'function'){
Array.prototype.some =
function(fn, context){
var arr = [];
if (
typeof fn ===
"function") {
for (
var k =
0, length =
this.length; k < length; k++) {
fn.call(context,
this[k], k,
this) && arr.push(
this[k]);
}
}
return arr;
}
}
|
数组聚合
[].reduce(fn, initialValue) / [].reduceRight(fn, initialValue)
- 将数组元素聚合(合并)为一个元素
- fn 的参数依次为 (之前值、当前值、索引值、数组本身),
- initialValue 表示最初的值,如果不存在,初始值为数组第1个元素
reduceRight
与 reduce
用法一致,区别是从最后一个元素开始迭代
var res = [
1,
2,
3,
4].reduce(
function(prev, curr, index, arr){
console.log(prev, curr, index, arr);
return prev+=curr;
})
console.log(res);
[
1,
2,
3,
4].reduce(
function(prev, curr, index, arr){
console.log(prev, curr, index, arr);
return prev+=curr;
},
10)
[
1,
2,
3,
4].reduceRight(
function(prev, curr, index, arr){
console.log(prev, curr, index, arr);
return prev+=curr;
})
[[
1,
2],[
3,
4]].reduce(
(prev,curr)=>prev.concat(curr))
if (
typeof
Array.prototype.reduce !=
"function") {
Array.prototype.reduce =
function (fn, initialValue ) {
var prev = initialValue, k =
0, len =
this.length;
if (
typeof initialValue ===
"undefined") {
prev =
this[
0];
k =
1;
}
if (
typeof fn ===
"function") {
for (k; k < len; k++) {
this.hasOwnProperty(k) && (prev = callback(prev,
this[k], k,
this));
}
}
return previous;
};
}
if (
typeof
Array.prototype.reduceRight !=
"function") {
Array.prototype.reduceRight =
function (fn, initialValue ) {
var len =
this.length, k = len -
1, prev = initialValue;
if (
typeof initialValue ===
"undefined") {
prev =
this[len -
1];
k--;
}
if (
typeof fn ===
"function") {
for (k; k >
-1; k--) {
this.hasOwnProperty(k) && (prev = callback(prev,
this[k], k,
this));
}
}
return previous;
};
}
|
ES6新增
- Array.from(arrLike) //类数组转数组
- Array.of(…args) //将一组值转成数组
- [].copyWithin(target, start, end) //复制数组成员到指定位置,会覆盖原有成员
- [].find(fn) // 查找元素,返回元素本身
- [].findIndex(fn) // 查找元素返回元素索引,没有则返回-1
- [].includes() // 检测数组是否包含某元素,返回true/false
- [].fill(value, start, end) //填充数组
- [].keys() // 返回数组的key组成的数组
- [].values() // 返回数组的值组成的数组
- [].entries() // 返回数组索引和值组成的数组
数组转换
Array.from(arrLike) / Array.of(...args)
Array.from
可以将类数组(有length属性的Object/可遍历(iterable)的对象/Set对象/Map对象)转换为数组
let arrayLike = {
'0':
'a',
'1':
'b',
'2':
'c',
length:
3};
[].slice.call(arrayLike)
let arr1 =
Array.from(arrayLike);
let set =
new
Set([
1,
3,
4,
5]);
let arr2 =
Array.from(set);
let map =
new
Map([[
1,
'a'], [
2,
'b'], [
3,
'c']]);
let arr3 =
Array.from(map);
let arr = [
1,
2,
3,
4];
let iter = arr[
Symbol.iterator]();
iter.next();
let arr4 =
Array.from(iter);
|
Array.of
用于将一组值转换为数组
使用 Array
的构造函数初始化数组时,如果参数是1个,那么会创建这个参数长度的数组,数组的每一项为 undefined
,如果参数是多个,那么会创建这多个参数组成的数组,所以参数的个数会导致结果的不一致,Array.of
正是弥补这一点的扩展
Array(
2);
Array(
2,
3);
Array.of(
2);
Array.of(
2,
3);
|
数组元素复制、填充与查找
- [].copyWithin(target, start, end) 复制数组成员到指定位置,会覆盖原有成员
- [].fill(value, start, end) 填充数组
- [].find(fn) 查找元素,返回元素本身
- [].findIndex(fn) 查找元素返回元素索引,没有则返回-1
- [].includes(value, startIndex) 检测数组是否包含某元素,返回true/false
Array.prototype.copyWithin(target, start = 0, end = this.length)
copyWithin
的三个参数:
- target(必需):从该位置开始替换数据。
- start(可选):从该位置开始读取数据,默认为0。如果为负值,表示倒数。
- end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数。
fill
的三个参数
- value:要填充的元素
- start: 从哪里开始填充
- end: 从哪里填充结束
[
1,
2,
3,
4,
5].copyWithin(
0,
3,
4)
Array(
5).fill(
0);
|
- find、findIndex 都是用于查找符合条件的元素,都可发现NaN,弥补了indexOf的不足
- includes 用于检测是否含有某个元素,返回 true/false
区别:
- includes 返回true或false,参数是要查找的元素,第2个参数会查找的起始索引,可以是负数
- find 返回的查找到的元素,没有则返回undefined
- findIndex 返回的是元素的索引值,没有则返回-1
[
1,
2,
3,
4].find(
v=>v>
3);
[
1,
2,
3,
4].find(
v=>v>
4);
[
1,
2,
3,
4].findIndex(
v=>v>
2);
[
1,
2,
3,
4].findIndex(
v=>v>
4);
[
1,
2,
NaN].indexOf(
NaN);
[
1,
2,
NaN].find(
v=>
Object.is(v,
NaN));
[
1,
2,
NaN].findIndex(
v=>
Object.is(v,
NaN));
[
1,
2,
NaN].includes(
NaN);
[
1,
2,
3,
4].includes(
2,
2);
|
获取数组中的键和值
- [].keys() // 返回 key 组成的数组
- [].values() // 返回 value 组成的数组
- [].entries() // 返回 {key:value} 组成的数组
这三个函数都返回一个 iterator
遍历器对象,可以使用 for...of
循环遍历
let iter1 = [
1,
2,
3,
4].keys();
let iter2 = [
1,
2,
3,
4].values();
let iter3 = [
1,
2,
3,
4].entries();
for(
let item
of iter1){
console.log(item) };
for(
let item
of iter2){
console.log(item) };
for(
let [index, item]
of iter3){
console.log(index, item) };
|
改变数组的方法
- splice
- shift / pop
- unshift / push
- reverse / sort
- copyWithin / fill
不改变数组的方法
- indexOf / lastIndexOf
- toString / join
- concat / slice
- some / every / filter
- map / forEach
- reduce / reduceRight
- keys / values / entries
- find / findIndex / includes
返回新数组的方法 concat / slice / map
返回iterator对象的方法 keys / values / entries
数组空位
空位表示没有任何值,也不等于 undefined
in
运算符可以检测数组的某个key是否含有值
0
in [
undefined,
undefined];
0
in [,,];
|
数组方法对空位的处理
- forEach(), filter(), every() 和some()都会忽略空位。
- map()会跳过空位,但会保留这个值
- join()和toString()会将空位视为undefined,而undefined和null会被处理成空字符串。
[,
'a'].forEach(
(x,i) =>
console.log(i));
[
'a',,
'b'].filter(
x =>
true)
[,
'a'].every(
x => x===
'a')
[,
'a'].some(
x => x !==
'a')
[,
'a'].map(
x =>
1)
[,
'a',
undefined,
null].join(
'#')
[,
'a',
undefined,
null].toString()
|
数组乱序
sort+random
调用 sort
函数,随机返回 true
or false
来决定是否交换位置
var arr = [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9];
Array.prototype.shuffle =
function(){
var res =
this.slice();
return res.sort(
(a, b)=>
Math.random()
-0.5 )
}
arr.shuffle();
|
这种方法打乱的数组中,越往后面最大数字出现的概率越高,所以并不稳定
改进: 由于原数组大数在后小数在前,会出现以上结果,如果随机将首尾交换将产生较理想的结果
var arr = [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9];
Array.prototype.shuffle =
function(){
var res =
this.slice(), len = res.length;
res = res.concat(res).splice(~~(
Math.random()*len), len);
return res.sort(
function(){
return
Math.random() -
0.5});
}
arr.shuffle();
|
快速随机排序
例:数组有5个元素
- 第一次从前4个元素中随机一个元素与第5个元素交换
- 第二次从前3个元素中随机一个元素与第4个元素交换
- 第三次从前2个元素中随机一个元素与第3个元素交换
- 第四次将第1个元素中与第2个元素交换
var arr = [
0,
1,
2,
3,
4];
Array.prototype.shuffle =
function(){
var res =
this.slice(), i =
0, len = res.length, idx, temp;
for(i; i<len
-1; i++){
idx =
Math.floor(
Math.random() * (len - i));
temp = res[idx];
res[idx] = res[len - i
-1];
res[len - i
-1] = temp;
}
return res;
}
arr.shuffle();
|
效率高,循环次数少,稳定均匀,时间复杂度O(n-1)
随机至新数组
每次随机从原数组抽取一个元素,添加到新数组,直到原数组元素个数为0
var arr = [
0,
1,
2,
3,
4,
5,
6,
7,
8,
9];
Array.prototype.shuffle =
function(){
var res =
this.slice(), i=
0, len = res.length, idx=
0, newArr=[];
for(i; i<len; i++){
idx =
Math.floor(
Math.random()*(len-i));
newArr.push(res.splice(idx,
1)[
0]);
}
return newArr;
}
arr.shuffle();
|
效率比快速随机差一点,时间复杂度O(n)
数组去重
- for+for
- for + indexOf
- filter + indexOf
- sort + filter
- splice
- HashTable
- from + Set (ES6)
for+for
创建一个新的数组,对原数组进行两层for循环遍历比较,新数组里如果存在,则跳出循环,进入下一个,如果没有,则将元素添加至新数组,
最后返回这个去重后的新数组
var arr1 = [
1,
'2',
9,
1,
'1',
2,
4,
9];
Array.prototype.distinct =
function(){
var arr =
this, res = [], i=
0, j=
0, len = arr.length;
for(i; i<len; i++){
var item = arr[i];
for(j=
0; j<res.length; j++){
if(res[j] === item)
break;
}
j === res.length && res.push(item);
}
return res;
}
Array.prototype.distinct =
function(){
var arr =
this, res = [], i=
0, j, len = arr.length;
for(i; i<len; i++){
for(j=i+
1; j<len; j++){
if(arr[i] === arr[j]){
j = ++i;
}
}
log(i);
res.push(arr[i]);
}
return res;
}
arr1.distinct();
|
for+indexOf
与上面的原理相同,如果结果数组中不存在,则添加,否则继续循环下一次,时间复杂度O(n)
var arr1 = [
1,
'2',
9,
1,
'1',
2,
4,
9];
Array.prototype.distinct =
function(){
var arr =
this, res = [], i=
0, len = arr.length;
for(i; i<len; i++){
var item = arr[i];
(res.indexOf(item) ===
-1) && res.push(item);
}
return res;
}
|
filter+indexOf
使用filter替代上面的for循环
因为indexOf是返回元素中数组中第一次出现的索引,所以后面重复的元素返回的索引是第一次出现的索引,而不等于当前的索引,所以不会被返回
Array.prototype.distinct =
function(){
return
this.filter(
function(v, i, arr){
return arr.indexOf(v) === i;
})
}
|
splice去重
双层for循环对比加splice实现,发现重复的值,则删除掉,再将length减1,
Array.prototype.distinct =
function(){
var arr =
this.slice(), i=
0, j, len=arr.length;
for(i; i<len; i++){
for(j=i+
1; j<len; j++){
if(arr[i] === arr[j]){
arr.splice(j,
1);
len--;
j--;
}
}
}
return arr;
}
|
速度慢,占用内存高
sort+filter
先利用sort排序(重复的值会被排到一起),第一个直接返回,从第二个元素开始,相邻两个元素比较,如果不相等,则返回后面这个元素
Array.prototype.distinct =
function(){
return
this.concat().sort().filter(
function(v, i, arr){
return !i || v !== arr[i
-1];
})
}
|
Hash去重
- 将数组的元素做为Hash对象的键,如果Hash中不存在,则将元素添加到结果数组中,存在,则继续下一次循环
- 由于1和’1’在hash对象中的key是会被转换成字符串的,所以 1 和 ‘1’ 会被认为是同一个,这里使用
key = typeof(item) + item
来做为key值
Array.prototype.distinct =
function(){
var arr=
this, hash = {}, i=
0, res=[], len = arr.length, key;
for(i; i<len; i++){
key =
typeof(arr[i])+arr[i];
if(hash[key]!==
true){
res.push(arr[i]);
hash[key] =
true;
}
}
return res;
}
|
Hash去重的改进
- 当数组元素为Object复杂对象时,上面的方式就不适用了,如
{a:1} === {a:1} //false
- 将数组中的项序列化为字符串,做为Object的key,因为Oject的key值是字符串,1和‘1’会被认为是同一个键
var o = {};
o[
1]=
true; o[
'1']=
true;
console.log(o)
var o = {};
o[
JSON.stringify(
1)] =
true;
o[
JSON.stringify(
'1')] =
true;
o
var arr2 = [ {
a:
1 }, {
a:
1 }, [
1,
2 ], [
1,
2 ],
1,
1,
'1',
'1' ]
Array.prototype.distinct =
function(){
var hashTable = {};
return
this.filter(
function(v){
var key =
JSON.stringify(v);
var match =
Boolean(hashTable[key]);
return (match ?
false : hashTable[key] =
true);
})
}
|
ES6 的去重方法
Array.from()
将一个类数组转为数组,Set数据结构存储的元素是唯一的
Array.prototype.distinct =
function(){
return
Array.from(
new
Set(
this));
}
|
总结
上面几种去重方式,filter+indexOf相当较快,但不能去除复杂对象如{a:1}和{a:1}, hash去重最准确,但速度稍慢,for+splice效率最差,ES6的from+Set仍然不能对复杂对象去重
数组排序(跳转)
数组排序方法众多,可以有很多种算法,这里请参考 经典排序算法_集锦
reduce高级用法
reduce()
方法接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始合并,最终为一个值。
reduce() 函数接收2个参数(M: 必填, O: 可选):
- (M) 回调reducer 函数 处理先前的结算结果和下一个元素直到序列结束。
- (O) 初值 作为第一次调用回调时的第一个参数。
rr.reduce(function(prev, cur, index, arr) {});
- prev: 第一项的值或者上一次叠加的结果值
- cur: 当前会参与叠加的项
- index: 当前值的索引
- arr: 数组本身
var items = [{
price:
10}, {
price:
120}, {
price:
1000}];
var sum = items.reduce(
(prev, curr, i, arr) =>prev+curr.price,
0);
log(sum);
var sum = items.reduce(
(prev, curr, i, arr) =>prev+curr.price,
-20);
log(sum);
var reducers = {
totalInDollar:
function(state, item){
state.dollar += item.price;
return state;
},
totalInEuros:
function(state, item){
state.euros += item.price *
0.897424;
return state;
},
totalInPounds:
function(state, item){
state.dollar += item.price *
0.6923412;
return state;
},
totalInYen:
function(state, item){
state.dollar += item.price *
112.853;
return state;
}
}
var combineTotalPriceReducers =
function(reducers){
return
function(state, item){
return
Object.keys(reducers).reduce(
function(nextState, key){
reducers[key](state, item);
return state;
}, {})
}
}
var bigTotalPriceReducer = combineTotalPriceReducers(reducers);
var initialState = {
dollars:
0,
euros:
0,
yens:
0,
pounds:
0};
var totals = items.reduce(bigTotalPriceReducer, initialState);
|
计算字母在字符串中出现的次数
var result =
'abcawab'.split(
'').reduce(
function(res, cur){
res[cur] ? res[cur]++ : (res[cur] =
1);
return res;
},{});
log(result);
|
元素添加
- 尾部添加 效率: arr[arr.length] > push > concat
- 头部添加 效率:[1].concat(arr) > arr.unshift(1) (safari相反)
- 中间添加 arr.splice(arr.length/2, 0, 1)
多维数组扁平化
var arrs = [[
1,
2],[
3,
4,
5], [
6,
7,
8,
9]];
var res = [];
for (
var i =
0; i < arrs.length; ++i) {
for (
var j =
0; j < arrs[i].length; ++j)
res.push(arr[i][j]);
}
console.log(res);
[].concat.apply([], arrs);
arrs.reduce(
function(prev,curr){
return prev.concat(curr);
})
[].concat(...arrs);
|
清空数组
var a =[1,3]; a.length=0 与 a = []
两种清空数组的区别:
list=[]
将一个新的引用数组赋值给变量,其它的引用不受影响,以前的数组内容如果被引用的话,将存储在内存,会导致内存泄漏list.length
删除数组里的内容,将影响到其它引用
var foo = [
1,
2,
3];
var bar = [
1,
2,
3];
var foo2 = foo;
var bar2 = bar;
foo = [];
bar.length =
0;
console.log(foo, bar, foo2, bar2);
[] [] [
1,
2,
3] []
|
求平均值、最大值、最小值
Math
的 max
方法和 min
方法接收多个参数,分别返回参数中的最大值和最小值
Math.max(
1,
2,
3,
4);
Math.min(
1,
2,
3,
4);
var arr = [
1,
2,
3,
4];
Math.max.apply(
null, arr);
Math.min.apply(
null, arr);
Math.max(...arr);
Math.min(...arr);
var max = arr[
0];
arr.forEach(
v=>{ max = v > max ? v : max; })
let nums = [
2,
3,
4,
1,
2,
33,
12,
45];
let sum = nums.reduce(
(prev,curr)=>prev+=curr);
let avg = sum / nums.length;
|
扩展阅读