Array 对象
构造函数
静态方法
Array.isArray()
实例方法
valueOf(),toString()
push(),pop()
shift(),unshift()
join(分隔符) 返回字符串
concat() 新的
reverse()
slice(头尾) 新的
splice(头,长,增) 增(头,0,增)拆成两个(头)返回删除的
sort()
map() 新的 this
forEach()不返回 this
filter()新的 返回 ture 的
some(),every() 新的 返 turee false
reduce(),reduceRight()新的
indexOf(),lastIndexOf() 新的
链式使用
1. 构造函数
Array 构造函数有一个很大的缺陷,就是不同的参数,会导致它的行为不一致。
// 无参数时,返回一个空数组
new Array() // []
// 单个正整数参数,表示返回的新数组的长度
new Array(1) // [empty]
new Array(2) // [empty x 2]
// 非正整数的数值作为参数,会报错
new Array(3.2) // RangeError: Invalid array length
new Array(-3) // RangeError: Invalid array length
// 单个非数值(比如字符串、布尔值、对象等)作为参数,
// 则该参数是返回的新数组的成员
new Array(‘abc’) // [‘abc’]
new Array([1]) // [Array[1]]
// 多参数时,所有参数都是返回的新数组的成员
new Array(1, 2) // [1, 2]
new Array(‘a’, ‘b’, ‘c’) // [‘a’, ‘b’, ‘c’]
// bad
var arr = new Array(1, 2);
// good
var arr = [1, 2];
var a = new Array(3);
var b = [undefined, undefined, undefined];
a.length // 3
b.length // 3
a[0] // undefined
b[0] // undefined
0 in a // false
0 in b // true
2. 静态方法
Array.isArray()
var arr = [1, 2, 3];
typeof arr // “object”
Array.isArray(arr) // true
3. 实例方法
3.1valueOf() 原数组,toString()字符串
3.2push(),pop() 改
3.3shift(),unshift() 改
shift()方法可以遍历并清空一个数组。
var list = [1, 2, 3, 4];
var item;
while (item = list.shift()) {
console.log(item);
}
list // []
上面代码通过 list.shift()方法每次取出一个元素,从而遍历数组。它的前提是数组元素不能是 0 或任何布尔值等于 false 的元素,因此这样的遍历不是很可靠
3.4join(分隔符)字符串
如果数组成员是 undefined 或 null 或空位,会被转成空字符串。
[undefined, null].join(‘#’)
// ‘#’
[‘a’,, ‘b’].join(‘-‘)
// ‘a–b’
通过 call 方法,这个方法也可以用于字符串或类似数组的对象。
Array.prototype.join.call(‘hello’, ‘-‘)
// “h-e-l-l-o”
var obj = {0: ‘a’, 1: ‘b’, length: 2};
Array.prototype.join.call(obj, ‘-‘)
// ‘a-b’
3.5concat()新
concat 方法返回当前数组的一个浅拷贝。所谓“浅拷贝”,指的是新数组拷贝的是对象的引用。
var obj = {a: 1};
var oldArray = [obj];
var newArray = oldArray.concat();
obj.a = 2;
newArray[0].a // 2
上面代码中,原数组包含一个对象,concat 方法生成的新数组包含这个对象的引用。所以,改变原对象以后,新数组跟着改变
3.6reverse()改
3.7slice(头,尾) 新
slice 方法的一个重要应用,是将类似数组的对象转为真正的数组。
Array.prototype.slice.call({0: ‘a’, 1: ‘b’, length: 2})
// [‘a’, ‘b’]
Array.prototype.slice.call(document.querySelectorAll(“div”));
Array.prototype.slice.call(arguments);
3.8splice(头,长,增) 只插入(头,0,增)
起始位置如果是负数,就表示从倒数位置开始删除。
var a = [‘a’, ‘b’, ‘c’, ‘d’, ‘e’, ‘f’];
a.splice(-4, 2) // [“c”, “d”]
上面代码表示,从倒数第四个位置 c 开始删除两个成员。
如果只是单纯地插入元素,splice 方法的第二个参数可以设为 0。
var a = [1, 1, 1];
a.splice(1, 0, 2) // []
a // [1, 2, 1, 1]
如果只提供第一个参数,等同于将原数组在指定位置拆分成两个数组。
var a = [1, 2, 3, 4];
a.splice(2) // [3, 4]
a // [1, 2]
3.9sort()改
数值会被先转成字符串,再按照字典顺序进行比较,所以 101 排在 11 的前面。
如果想让 sort 方法按照自定义方式排序,可以传入一个函数作为参数。
[10111, 1101, 111].sort(function (a, b) {
return a – b;
})
// [111, 1101, 10111]
上面代码中,sort 的参数函数本身接受两个参数,表示进行比较的两个数组成员。如果该函数的返回值大于 0,表示第一个成员排在第二个成员后面;其他情况下,都是第一个元素排在第二个元素前面。
[
{name: “ 张三 ”, age: 30},
{name: “ 李四 ”, age: 24},
{name: “ 王五 ”, age: 28}
].sort(function (o1, o2) {
return o1.age – o2.age;
})
// [
// {name: “ 李四 ”, age: 24},
// {name: “ 王五 ”, age: 28},
// {name: “ 张三 ”, age: 30}
// ]
3.10map()新
[1, 2, 3].map(function(elem, index, arr) {
return elem * index;
});
// [0, 2, 6]
上面代码中,map 方法的回调函数有三个参数,elem 为当前成员的值,index 为当前成员的位置,arr 为原数组([1, 2, 3])。
map 方法还可以接受第二个参数,用来绑定回调函数内部的 this 变量(详见《this 变量》一章)。
var arr = [‘a’, ‘b’, ‘c’];
[1, 2].map(function (e) {
return this[e];
}, arr)
// [‘b’, ‘c’]
上面代码通过 map 方法的第二个参数,将回调函数内部的 this 对象,指向 arr 数组。
如果数组有空位,map 方法的回调函数在这个位置不会执行,会跳过数组的空位。
var f = function (n) {return ‘a’};
[1, undefined, 2].map(f) // [“a”, “a”, “a”]
[1, null, 2].map(f) // [“a”, “a”, “a”]
[1, , 2].map(f) // [“a”, , “a”]
上面代码中,map 方法不会跳过 undefined 和 null,但是会跳过空位。
3.11forEach()
forEach 方法不返回值,只用来操作数据。这就是说,如果数组遍历的目的是为了得到返回值,那么使用 map 方法,否则使用 forEach 方法
function log(element, index, array) {
console.log(‘[‘ + index + ‘] = ‘ + element);
}
[2, 5, 9].forEach(log);
// [0] = 2
// [1] = 5
// [2] = 9
forEach 方法也可以接受第二个参数,绑定参数函数的 this 变量。
var out = [];
[1, 2, 3].forEach(function(elem) {
this.push(elem * elem);
}, out);
out // [1, 4, 9]
上面代码中,空数组 out 是 forEach 方法的第二个参数,结果,回调函数内部的 this 关键字就指向 out。
forEach 方法也会跳过数组的空位。
var log = function (n) {
console.log(n + 1);
};
[1, undefined, 2].forEach(log)
// 2
// NaN
// 3
[1, null, 2].forEach(log)
// 2
// 1
// 3
[1, , 2].forEach(log)
// 2
// 3
3.12filter()
[1, 2, 3, 4, 5].filter(function (elem) {
return (elem > 3);
})
// [4, 5]
上面代码将大于 3 的数组成员,作为一个新数组返回。
var arr = [0, 1, ‘a’, false];
arr.filter(Boolean)
// [1, “a”]
上面代码中,filter 方法返回数组 arr 里面所有布尔值为 true 的成员
[1, 2, 3, 4, 5].filter(function (elem, index, arr) {
return index % 2 === 0;
});
// [1, 3, 5]
filter 方法还可以接受第二个参数,用来绑定参数函数内部的 this 变量。
var obj = {MAX: 3};
var myFilter = function (item) {
if (item > this.MAX) return true;
};
var arr = [2, 8, 3, 4, 1, 3, 2, 9];
arr.filter(myFilter, obj) // [8, 4, 9
3.13some(),every()
判断数组成员是否符合某种条件
some 方法是只要一个成员的返回值是 true,则整个 some 方法的返回值就是 true,否则返回 false
var arr = [1, 2, 3, 4, 5];
arr.some(function (elem, index, arr) {
return elem >= 3;
});
// true
上面代码中,如果数组 arr 有一个成员大于等于 3,some 方法就返回 true。
every 方法是所有成员的返回值都是 true,整个 every 方法才返回 true,否则返回 false。
var arr = [1, 2, 3, 4, 5];
arr.every(function (elem, index, arr) {
return elem >= 3;
});
// false
上面代码中,数组 arr 并非所有成员大于等于 3,所以返回 false。
注意,对于空数组,some 方法返回 false,every 方法返回 true,回调函数都不会执行。
function isEven(x) {return x % 2 === 0}
[].some(isEven) // false
[].every(isEven) // true
some 和 every 方法还可以接受第二个参数,用来绑定参数函数内部的 this 变量。
3.14reduce(),reduceRight()
reduce 方法和 reduceRight 方法依次处理数组的每个成员,最终累计为一个值。它们的差别是,reduce 是从左到右处理(从第一个成员到最后一个成员),reduceRight 则是从右到左(从最后一个成员到第一个成员),其他完全一样。
[1, 2, 3, 4, 5].reduce(function (a, b) {
console.log(a, b);
return a + b;
})
// 1 2
// 3 3
// 6 4
// 10 5
// 最后结果:15
上面代码中,reduce 方法求出数组所有成员的和。第一次执行,a 是数组的第一个成员 1,b 是数组的第二个成员 2。第二次执行,a 为上一轮的返回值 3,b 为第三个成员 3。第三次执行,a 为上一轮的返回值 6,b 为第四个成员 4。第四次执行,a 为上一轮返回值 10,b 为第五个成员 5。至此所有成员遍历完成,整个方法的返回值就是最后一轮的返回值 15。
reduce 方法和 reduceRight 方法的第一个参数都是一个函数。该函数接受以下四个参数。
累积变量,默认为数组的第一个成员
当前变量,默认为数组的第二个成员
当前位置(从 0 开始)
原数组
这四个参数之中,只有前两个是必须的,后两个则
如果要对累积变量指定初值,可以把它放在 reduce 方法和 reduceRight 方法的第二个参数。
[1, 2, 3, 4, 5].reduce(function (a, b) {
return a + b;
}, 10);
// 25
上面代码指定参数 a 的初值为 10,所以数组从 10 开始累加,最终结果为 25。注意,这时 b 是从数组的第一个成员开始遍历
上面的第二个参数相当于设定了默认值,处理空数组时尤其有用。
function add(prev, cur) {
return prev + cur;
}
[].reduce(add)
// TypeError: Reduce of empty array with no initial value
[].reduce(add, 1)
// 1
上面代码中,由于空数组取不到初始值,reduce 方法会报错。这时,加上第二个参数,就能保证总是会返回一个值
下面是一个 reduceRight 方法的例子。
function subtract(prev, cur) {
return prev – cur;
}
[3, 2, 1].reduce(subtract) // 0
[3, 2, 1].reduceRight(subtract) // -4
上面代码中,reduce 方法相当于 3 减去 2 再减去 1,reduceRight 方法相当于 1 减去 2 再减去 3。
由于这两个方法会遍历数组,所以实际上还可以用来做一些遍历相关的操作。比如,找出字符长度最长的数组成员。
function findLongest(entries) {
return entries.reduce(function (longest, entry) {
return entry.length > longest.length ? entry : longest;
}, ”);
}
findLongest([‘aaa’, ‘bb’, ‘c’]) // “aaa”
上面代码中,reduce 的参数函数会将字符长度较长的那个数组成员,作为累积值。这导致遍历所有成员之后,累积值就是字符长度最长的那个成员。
3.15indexOf(),lastIndexOf()
3.16 链式使用