Array
Array 的构造器
// 使用 Array 构造器,可以自定义长度
var a = Array(6); // [empty × 6]
// 使用对象字面量
var b = [];
b.length = 6; // [undefined × 6]
// new Array(arg1, arg2,…),参数长度为 0 或长度大于等于 2 时,传入的参数将按照顺序依次成为新数组的第 0 至第 N 项(参数长度为 0 时,返回空数组);
new Array() // []
new Array(1) // [empty]
new Array(2) // [empty, empty]
new Array(1,2) // [1,2]
new Array(1,2,3) // [1,2,3]
// Array.of
Array.of(8.0); // [8]
Array(8.0); // [empty × 8]
Array.of(8.0, 5); // [8, 5]
Array(8.0, 5); // [8, 5]
Array.of('8'); // ["8"]
Array('8'); // ["8"]
////////////////////////////////////////////////////////////////
//Array.from
// 1.类似数组的对象,必选;
// 2.加工函数,新生成的数组会经过该函数的加工再返回;
// 3.this 作用域,表示加工函数执行时 this 的值。
var obj = {0: 'a', 1: 'b', 2:'c', length: 3};
Array.from(obj, function(value, index){
console.log(value, index, this, arguments.length);
return value.repeat(3); //必须指定返回值,否则返回 undefined
}, obj);
// a 0 {0: 'a', 1: 'b', 2: 'c', length: 3} 2
// b 1 {0: 'a', 1: 'b', 2: 'c', length: 3} 2
// c 2 {0: 'a', 1: 'b', 2: 'c', length: 3} 2
// (3) ['aaa', 'bbb', 'ccc']
// String
Array.from('abc'); // ["a", "b", "c"]
// Set
Array.from(new Set(['abc', 'def'])); // ["abc", "def"]
// Map
Array.from(new Map([[1, 'ab'], [2, 'de']]));
// [[1, 'ab'], [2, 'de']]
////////////////////////////////////////////////////////////////
Array 的判断
var a = [];
// 1.基于instanceof
a instanceof Array;
// 2.基于constructor
a.constructor === Array;
// 3.基于Object.prototype.isPrototypeOf
Array.prototype.isPrototypeOf(a);
// 4.基于getPrototypeOf
Object.getPrototypeOf(a) === Array.prototype;
// 5.基于Object.prototype.toString
Object.prototype.toString.apply(a) === '[object Array]';
// 6.基于Array.isArray
Array.isArray([])
改变自身的方法
基于 ES6,会改变自身值的方法一共有 9 个,分别为 pop、push、reverse、shift、sort、splice、unshift,以及两个 ES6 新增的方法 copyWithin 和 fill。
// pop方法 返回值是删除的数组项
var array = ["cat", "dog", "cow", "chicken", "mouse"];
var item = array.pop();
console.log(array); // ["cat", "dog", "cow", "chicken"]
console.log(item); // mouse
// push方法 返回值是新数组的长度
var array = ["football", "basketball", "badminton"];
var i = array.push("golfball");
console.log(array);
// ["football", "basketball", "badminton", "golfball"]
console.log(i); // 4
// reverse方法
var array = [1,2,3,4,5];
var array2 = array.reverse();
console.log(array); // [5,4,3,2,1]
console.log(array2===array); // true
// shift方法 删除第一个元素 返回的是删除的数组项
var array = [1,2,3,4,5];
var item = array.shift();
console.log(array); // [2,3,4,5]
console.log(item); // 1
// unshift方法 添加第一个元素 返回是新数组的长度
var array = ["red", "green", "blue"];
var length = array.unshift("yellow");
console.log(array); // ["yellow", "red", "green", "blue"]
console.log(length); // 4
// sort方法 排序
var array = ["apple","Boy","Cat","dog"];
var array2 = array.sort();
console.log(array); // ["Boy", "Cat", "apple", "dog"]
console.log(array2 == array); // true
// splice方法
var array = ["apple","boy"];
var splices = array.splice(1,1); // 从第一个开始,删除1个元素 返回值是删除项
console.log(array); // ["apple"]
console.log(splices); // ["boy"]
var splices1 = array.splice(0, 0, 'girl') // 从第0个开始,删除0个元素, 添加后面的元素
console.log(array); // ['girl',"apple"]
console.log(splices); // [""]
// copyWithin方法 (target, start, end)
var array = [1,2,3,4,5];
var array2 = array.copyWithin(0,3); // 目标是0下边,从第三个开始到最后取得是4,5 放到0,1位置
console.log(array===array2,array2); // true [4, 5, 3, 4, 5]
// fill方法 数组填充 value,start,end
var array = [1,2,3,4,5];
var array2 = array.fill(10,0,3);
console.log(array===array2,array2);
// true [10, 10, 10, 4, 5], 可见数组区间[0,3]的元素全部替换为10
// 下面为了让你对这些 API 方法有更深刻的印象,我结合 Leetcode 中的第 88 题 《合并两个有序数组》,带你看下如何利用数组的多个改变自身的方法来解决这道题,题目是这样的:
// 给你两个有序整数数组 nums1 和 nums2,请你将 nums2 合并到 nums1 中,使 nums1 成为一个有序数组。
// 输入:
// nums1 = [1,2,3,0,0,0]; m = 3
// nums2 = [2,5,6]; n = 3
// 输出: [1,2,2,3,5,6]
var merge = function(nums1, m, nums2, n) {
nums1.splice(m);
nums2.splice(n);
nums1.push(...nums2);
nums1.sort((a,b) => a - b); // nums1从小到大排列,所以是a-b
};
不改变自身的方法
基于 ES7,不会改变自身的方法也有 9 个,分别为 concat、join、slice、toString、toLocaleString、indexOf、lastIndexOf、未形成标准的 toSource,以及 ES7 新增的方法 includes。
// concat方法 数据拼接
var array = [1, 2, 3];
var array2 = array.concat(4,[5,6],[7,8,9]);
console.log(array2); // [1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log(array); // [1, 2, 3], 可见原数组并未被修改
// join方法
var array = ['We', 'are', 'Chinese'];
console.log(array.join()); // "We,are,Chinese"
console.log(array.join('+')); // "We+are+Chinese"
// slice方法 截取数组 start = 0, end
var array = ["one", "two", "three","four", "five"];
console.log(array.slice()); // ["one", "two", "three","four", "five"]
console.log(array.slice(2,3)); // ["three"]
// toString方法
var array = ['Jan', 'Feb', 'Mar', 'Apr'];
var str = array.toString();
console.log(str); // Jan,Feb,Mar,Apr
// tolocalString方法
var array= [{name:'zz'}, 123, "abc", new Date()];
var str = array.toLocaleString();
console.log(str); // [object Object],123,abc,2016/1/5 下午1:06:23
// indexOf方法 获取元素下标 lastIndexOf从后边往前找
var array = ['abc', 'def', 'ghi','123'];
console.log(array.indexOf('def')); // 1
// includes方法
var array = [-0, 1, 2];
console.log(array.includes(+0)); // true
console.log(array.includes(1)); // true
var array = [NaN];
console.log(array.includes(NaN)); // true
数组遍历的方法
基于 ES6,不会改变自身的遍历方法一共有 12 个,分别为 forEach、every、some、filter、map、reduce、reduceRight,以及 ES6 新增的方法 entries、find、findIndex、keys、values。
// forEach方法
var array = [1, 3, 5];
var obj = {name:'cc'};
var sReturn = array.forEach(function(value, index, array){
array[index] = value;
console.log(this.name); // cc被打印了三次, this指向obj
},obj);
console.log(array); // [1, 3, 5]
console.log(sReturn); // undefined, 可见返回值为undefined
// every方法 每个都满足条件才是true
var o = {0:10, 1:8, 2:25, length:3};
var bool = Array.prototype.every.call(o,function(value, index, obj){
return value >= 8;
},o);
console.log(bool); // true
// some方法 有一个满足条件就是true
var array = [18, 9, 10, 35, 80];
var isExist = array.some(function(value, index, array){
return value > 20;
});
console.log(isExist); // true
// map 方法 遍历每一项,并处理返回
var array = [18, 9, 10, 35, 80];
array.map(item => item + 1);
console.log(array); // [19, 10, 11, 36, 81]
// filter 方法 过滤出符合条件的数组项
var array = [18, 9, 10, 35, 80];
var array2 = array.filter(function(value, index, array){
return value > 20;
});
console.log(array2); // [35, 80]
// reduce方法
// 首先是 callback(一个在数组的每一项中调用的函数,接受四个参数):
// previousValue(上一次调用回调函数时的返回值,或者初始值)
// currentValue(当前正在处理的数组元素)
// currentIndex(当前正在处理的数组元素下标)
// array(调用 reduce() 方法的数组)
// 然后是 initialValue(可选的初始值,作为第一次调用回调函数时传给 previousValue 的值)
var array = [1, 2, 3, 4];
var s = array.reduce(function(previousValue, value, index, array){
return previousValue * value;
},1);
console.log(s); // 24
/ ES6写法更加简洁
array.reduce((p, v) => p * v); // 24
// reduceRight方法 (和reduce的区别就是从后往前累计)
var array = [1, 2, 3, 4];
array.reduceRight((p, v) => p * v); // 24
// entries方法
var array = ["a", "b", "c"];
var iterator = array.entries();
console.log(iterator.next().value); // [0, "a"]
console.log(iterator.next().value); // [1, "b"]
console.log(iterator.next().value); // [2, "c"]
console.log(iterator.next().value); // undefined, 迭代器处于数组末尾时, 再迭代就会返回undefined
// find & findIndex方法
var array = [1, 3, 5, 7, 8, 9, 10];
function f(value, index, array){
return value%2==0; // 返回偶数
}
function f2(value, index, array){
return value > 20; // 返回大于20的数
}
console.log(array.find(f)); // 8
console.log(array.find(f2)); // undefined
console.log(array.findIndex(f)); // 4
console.log(array.findIndex(f2)); // -1
// keys方法 返回下标
[...Array(10).keys()]; // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
[...new Array(10).keys()]; // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
// values方法 返回值 迭代器
var array = ["abc", "xyz"];
var iterator = array.values();
console.log(iterator.next().value);//abc
console.log(iterator.next().value);//xyz
console.log(iterator.next().value); // undefined, 迭代器处于数组末尾时, 再迭代就会返回undefined
reduce
reduce 方法也需要重点关注,其参数复杂且多,通常一些复杂的逻辑处理,其实使用 reduce 很容易就可以解决。我们重点看一下,reduce 到底能解决什么问题呢?先看下 reduce 的两个参数。
首先是 callback(一个在数组的每一项中调用的函数,接受四个参数):
- previousValue(上一次调用回调函数时的返回值,或者初始值)
- currentValue(当前正在处理的数组元素)
- currentIndex(当前正在处理的数组元素下标)
- array(调用 reduce() 方法的数组) 然后是 initialValue(可选的初始值,作为第一次调用回调函数时传给 previousValue 的值)。
/* 题目:数组 arr = [1,2,3,4] 求数组的和:*/
// 第一种方法:
var arr = [1,2,3,4];
var sum = 0;
arr.forEach(function(e){sum += e;}); // sum = 10
// 第二种方法
var arr = [1,2,3,4];
var sum = 0;
arr.map(function(obj){sum += obj});
// 第三种方法
var arr = [1,2,3,4];
arr.reduce(function(pre,cur){return pre + cur});
/* 题目: var arr = [ {name: 'brick1'}, {name: 'brick2'}, {name: 'brick3'} ] 希望最后返回到 arr 里面每个对象的 name 拼接数据为 'brick1, brick2 & brick3' **/
var arr = [ {name: 'one'}, {name: 'two'}, {name: 'three'} ];
arr.reduce(function(prev, current, index, array){
if (index === 0){
return current.name;
} else if (index === array.length - 1){
return prev + ' & ' + current.name;
} else {
return prev + ', ' + current.name;
}
}, '');
// 返回结果 "one, two & three"
以上,数组的各方法基本讲解完毕,这些方法之间存在很多共性,如下:
- 所有插入元素的方法,比如 push、unshift 一律返回数组新的长度;
- 所有删除元素的方法,比如 pop、shift、splice 一律返回删除的元素,或者返回删除的多个元素组成的数组;
- 部分遍历方法,比如 forEach、every、some、filter、map、find、findIndex,它们都包含 function(value,index,array){} 和 thisArg 这样两个形参。