数组常用方法

103 阅读1分钟

www.runoob.com/jsref/jsref…

返回新数组,不改变原数组返回新数组,改变原数组(加减排序操作)其他
joinconcatsliceeverysomefilterpoppushshiftunshiftreversesort (默认排序顺序为按字母升序,ascii码)splicetoString()和toLocaleString()indexOf()和lastIndexOf()fromofcopyWithinfind()和findIndex()fillentries()、keys()、values() ['a','b'].keys()includes

map,forEach方法注意:

当数组元素是基本数据类型时,方法不会改变原数组;当数组元素是引用类型时,方法会改变原数组。 events.jianshu.io/p/d709fe2be…

原因是因为基本类型传值是复制,引用类型传值是引用

map(不会对空数组进行检测)

forEach(对于空数组是不会调用回调函数的, 不返回新数组)

reduce和reduceRight

let a = [1, 5, 6, 7, 8, 1, 5];
let b = a.reduce(function (pre, cur) {
  pre.indexOf(cur) === -1 && pre.push(cur);
  return pre;
}, []);
let c = a.reduce(function (pre, cur) {
  return pre + cur;
}, 0);

数组去重: juejin.im/post/5c7b8b…

好用的(完美解决)一般的
ES6 的 Set 对象Map 的 has 方法includesreducelodash 中的 _.uniqindexOf  没处理 NaNsort 没处理 NaN双层 for 循环 + splice 没处理 NaN原始去重 没处理 NaNfilter + hasOwnProperty 存在问题对象的属性 把 {} 给处理了
// Map去重
let arr = [1, 2, 3, 1, 2, 3, "a", "a", "b"];
function arrayNoRepeat(arr) {
  let map = new Map();
  let result = new Array(); // 数组用于返回结果
  for (let i = 0; i < arr.length; i++) {
    if (!map.has(arr[i])) {
      // 判断 map 中是否已有该 key 值
      map.set(arr[i], true);
      result.push(arr[i]);
    }
  }
  return result;
}
console.log(arrayNoRepeat(arr));
//[1, 2, 3, "a", "b"]

// Set去重
const set = new Set([1, 2, 3, 4, 4]);
[...set];
// [1, 2, 3, 4]

所谓类似数组的对象,本质特征只有一点,即必须有length属性。因此,任何有length属性的对象,都可以通过Array.from方法转为数组,而此时扩展运算符就无法转换。

对Array.apply(null, { length: 10 })的解释

ES5开始apply函数的第二个参数除了可以是数组外,还可以是类数组对象(即包含length属性,且length属性值是个数字的对象)。对象{length: 2}就是一个类数组对象,因为没有初始化下标0,1的值,所以获取0,1下标的值得到的都是undefined。

// 1 熟悉一点: {length: 2}作为Array.apply第二个参数等同于[undefined, undefined]作为Array.apply第二个参数 Array.apply(null, [undefined, undefined]);

// 2 再熟悉一点:apply方法的执行结果 Array(undefined, undefined);

// 3 再再熟悉一点:Array方法直接调用和new方式调用等价 new Array(undefined, undefined);

为啥非要写那么复杂呢?

map函数并不会遍历数组中没有初始化或者被delete的元素(有相同限制还有forEach, reduce方法)。OK,疑问到此终于真相大白了:写这么“复杂”就是为了实现:创建一个长度为20,且每个元素都被初始化的数组。这样map方法就可以循环20次了。

// 被初始化的数组 
Array.apply(null, { length: 20 }).map(function (val, index) {
  console.log(index); // 循环20次
});
// 未被初始化的数组 
Array(20).map(function (val, index) {
  console.log(index); // 不会被执行
});

创建一个长度为100的数组

microzz.com/2017/03/24/…

1.传统for循环

var arr = new Array(100);
for (var i = 0; i < arr.length; i++) {
  arr[i] = i;
}
arr; // [0, 1, ..., 99]

2.ES5的实现

Object.keys(Array.apply(null, { length: 100 }));

这样似乎的确完成了功能,但是还有一个问题,此时值是字符串类型, 所以我们可以用ES5的map方法进行处理一下: 

Object.keys(Array.from({ length: 100 })).map(function (item) {
  return +item;
});

3.ES6的实现

//ES6中数组实例有keys、values、entries方法,
//分别用于遍历数组的索引、键值、键值对, 它们都返回遍历器对象(详细👉Iterator和for…of循环)
Object.keys(Array.from({ length: 100 })); // ["0", "1", "2", ..., "98", "99"] 
Array.from(new Array(100).keys()); //Array.from其实还有一个回调函数,可以很方便遍历处理每一个数据
Array.from({ length: 100 }, (v, i) => i);
Array.from(Array(100), (v, i) => i); // [0, 1, 2, ..., 98, 99]

4.扩展运算符

[...Array(100).keys()];
//或者
[...Array.from({ length: 100 }).keys()];