1. 数组降维 二维数组降维成一维数组(引自vue源码)
利用原理: (1) concat的属性 : 如果concat方法的参数是一个元素,该元素会被直接插入到新数组中;如果参数是一个数组,该数组的各个元素将被插入到新数组中; (2) apply的优化:Array.prototype.concat.apply([], children) 等同于 [].concat(demoArr)
 
1 2 3 4 5 6 7 8 9 10 11 12 let  demoArr = [1 ,2 ,3 ,4 ,5 ,[7 ,8 ],[22 ,23 ,43 ]]export  function  simpleNormalizeChildren  (children )  {  for  (let  i = 0 ; i < children.length; i++) {     if  (Array .isArray(children[i])) {       return  Array .prototype.concat.apply([], children)     }   }   return  children } simpleNormalizeChildren(demoArr)   
 
扩展: 多维数组递归降维(借助了递归的能力)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 let  children = [1 , [2 ,3 ], [4 , [5 , 6 , [7 , 8 ]]], [9 , 10 ]];function  simpleNormalizeChildren (children )  {  for  (let  i = 0 ; i < children.length; i++) {     if  (Array .isArray(children[i])) {       children = Array .prototype.concat.apply([], children);       for (let  j =0 ; j<children.length; j++) {         simpleNormalizeChildren(children)       }     }   }   return  children; } simpleNormalizeChildren(children);  
 
2. 数组去重 (1) ES6 set方法 (Set 对象允许你存储任何类型的唯一值)
1 2 3 4 5 6 7 function  unique  (arr )  {  return  Array .from(new  Set (arr)) } var  arr = [1 ,1 ,'true' ,'true' ,true ,true ,15 ,15 ,false ,false , undefined ,undefined , null ,null , NaN , NaN ,'NaN' , 0 , 0 , 'a' , 'a' ,{},{}]; console .log(unique(arr))  
 
  set方法无法识别重复的{}空对象
 
(2)双重for循环,splice去重
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 function  unique (arr ) {                    for (var  i=0 ; i<arr.length; i++){             for (var  j=i+1 ; j<arr.length; j++){                 if (arr[i]==arr[j]){                              arr.splice(j,1 );                     j--;                  }             }         } return  arr;} var  arr = [1 ,1 ,'true' ,'true' ,true ,true ,15 ,15 ,false ,false , undefined ,undefined ,     null ,null , NaN , NaN ,'NaN' , 0 , 0 , 'a' , 'a' ,{},{}];     console .log(unique(arr))      
 
NaN和{}没有去重,两个null直接消失了
(3) indexOf(新建了一个空数组,遍历旧数组,如果空数组里没遇到重复的遍历项,则添加) 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 function  unique (arr )  {    if  (!Array .isArray(arr)) {         console .log('type error!' )         return      }     var  array = [];     for  (var  i = 0 ; i < arr.length; i++) {         if  (array.indexOf(arr[i]) === -1 ) {             array.push(arr[i])         }     }     return  array; } var  arr = [1 ,1 ,'true' ,'true' ,true ,true ,15 ,15 ,false ,false , undefined ,undefined ,           null ,null , NaN , NaN ,'NaN' , 0 , 0 , 'a' , 'a' ,{},{}]; console .log(unique(arr))    
 
NaN、{}没有去重
(4) sort排序后再去重(sort后一样的元素的会在旁边,只需与身边的对比)高性能,推荐👍
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 function  unique (arr )  {  var  seen;       var  targetArr = Array .prototype.concat.call(arr).sort()    var  result = [];      for  (var  i = 0 ; i <targetArr.length; i++) {                 if  (!i || seen !== targetArr[i]) {       result.push(targetArr[i])     }          seen = targetArr[i]   }   return  result } var  arr = [1 ,1 ,'true' ,'true' ,true ,true ,15 ,15 ,false ,false , undefined ,undefined ,         null ,null , NaN , NaN ,'NaN' , 0 , 0 , 'a' , 'a' ,{},{}]; console .log(unique(arr));
 
  sort方法需要注意看使用场景,特殊类型的时候,sort会有坑。
(5) underScore 思路版 (提供三个参数)这个思路杂糅上面的方法  array: 必填参数,去重目标数组isSorted: 表示目标数组是否已经排序过了,true的话,将会采用方法(4)那样的高效对比。false的话,用indexOfiteratee: 自定义对目标数组的操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 function  unique (array, isSorted, iteratee )  {    var  res = [];     var  seen = [];     for  (var  i = 0 , len = array.length; i < len; i++) {         var  value = array[i];         var  computed = iteratee ? iteratee(value, i, array) : value;         if  (isSorted) {             if  (!i || seen !== computed) {                 res.push(value)             }             seen = computed;         }         else  if  (iteratee) {             if  (seen.indexOf(computed) === -1 ) {                 seen.push(computed);                 res.push(value);             }         }         else  if  (res.indexOf(value) === -1 ) {             res.push(value);         }             }     return  res; } console .log(unique(array3, false , function (item ) {    return  typeof  item == 'string'  ? item.toLowerCase() : item }));  
 
(6) 利用Object的key是唯一的
1 2 3 4 5 6 7 8 function  distinct (array )  {    var  obj = {};     return  array.filter(function (item, index, array ) {         return  obj.hasOwnProperty(typeof  item + item)          ? false          : (obj[typeof  item + item] = true )     }) } 
 
真是叹为观止,妙!妙在哪?
array.filter本身就兼职遍历,过滤,返回新数组于一身,干净利落 
Object的key确实是唯一的,如果重复时候,只能是覆盖value的 
filter过滤条件需要的true和false就由 Obj是否包含这个type+value为key  来决定, 如果之前没存进obj,可以任意设置一个value,就是三元运算符里的obj[typeof item + item] = true 
 
 
API补充: 
reduce 
 
升序让数组每一项都调用传入函数,可以设置初始值。 四个参数Accumulator (acc) (累计器)Current Value (cur) (当前值)Current Index (idx) (当前索引)Source Array (src) (源数组)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])`` `  ` `` javascriptvar  names = ['Alice' , 'Bob' , 'Tiff' , 'Bruce' , 'Alice' ];var  countedNames = names.reduce(function  (allNames, name )  {   if  (name in  allNames) {     allNames[name]++;   }   else  {     allNames[name] = 1 ;   }   return  allNames; }, {}); 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 var  pipe = (function ( ) {       return  function  (value )  {            var  funcStack = [];           var  oproxy = new  Proxy ({} , {               get  : function  (pipeObject, fnName )  {                   console .log('fnName is:'  + fnName)                   if  (fnName === 'get' ) {                       return  funcStack.reduce(function  (val, fn )  {                           return  fn(val);                       },value);                   }                   funcStack.push(window [fnName]);                   console .log(funcStack)                   return  oproxy;               }           });           return  oproxy;       }   }());   var  double = n  =>  n * 2 ;   var  pow    = n  =>  n * n;   var  reverseInt = n  =>  n.toString().split("" ).reverse().join("" ) | 0 ;   console .log(pipe(3 )['double' ].pow.get);    
 
slice 类数组 => 真数组
1 2 3 4 5 6 function  list ( )  {     return  Array .prototype.slice.call(arguments );  } var  list1 = list(1 , 2 , 3 ); 
 
Array.from 从一个类似数组或可迭代对象创建一个新的,浅拷贝的数组实例。
1 Array .from(arrayLike[, mapFn[, thisArg]])
 
arrayLike:想要转换成数组的伪数组对象或可迭代对象。比如拥有一个 length 属性和若干索引属性的任意对象和Map、set等。mapFn 可选:如果指定了该参数,新数组中的每个元素会执行该回调函数。thisArg 可选:可选参数,执行回调函数 mapFn 时 this 对象。
 
 
1 2 const  someNumbers = { '0' : 10 , '1' : 15 , length : 2  };Array .from(someNumbers, value  =>  value * 2 ); 
 
1 2 3 4 function  sumArguments ( )  {    return  Array .from(arguments ).reduce((sum, num ) =>  sum + num); } sumArguments(1 , 2 , 3 );  
 
Array.concat() 不传参数的时候,是一种浅拷贝的行为
 
Array.filter(function(){})  如名,filter,过滤,该方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。不改变原数组
 
 
1 var  newArray = arr.filter(callback(element[, index[, array]])[, thisArg])
 
callback: 用来测试数组元素的函数 return true时 保留元素 否则不保留。index: 当前处理索引array: 调用了filter的数组本身
1 2 3 4 5   function  isBigEnough (element )  {   return  element >= 10 ; } var  filtered = [12 , 5 , 8 , 130 , 44 ].filter(isBigEnough);
 
参考 MDN - slice MDN - reduce MDN - typeof MDN - Array.from 掘金 reduce 掘金 Array.from 拉钩博文 冴羽 Array去重 issue 阮一峰 reduce transduce 关于 函数编程