Open evantianx opened 7 years ago
构造一个数组通常有两种方法,较为普遍的是对象字面量方法:
// 使用 Array 构造器
const a = Array(3)
// 使用对象字面量
const b = []
b.length = 3
我们在使用构造器的时候并没有添加关键字 new
,但仍然创建了一个数组实例,这是为什么呢?
规范上写到:
When
Array
is called as a function rather than as a constructor, it creates and initialises a new Array object. Thus the function call Array(…) is equivalent to the object creation expressionnew Array(…)
with the same arguments.
Array 构造器语法如下:
new Array([item0[,item1[,...]]])
只有在构造器被传入参数个数为 0 或者至少 2 个的时候适用。
传入参数为 0 时返回一个空数组,传入参数不小于 2 时依次作为新数组成员构成一个新的数组。new Array(len)
传入参数为非数字类型时,按照第一条规则走,即将该参数作为数组唯一成员构成新数组;
传入参数为数字类型且ToUnit32(len)
与len
相等,此时参数作为数组长度处理。Array.of
用于将参数依次转换为数组中的一项,然后返回新数组,不论该参数为何种类型。
Array.of(1) // [1]
Array(1) // [undefined]
所以如果单单是为了用数组包裹元素,建议使用Array.of()
。
对于不支持 Array.of 的浏览器,可以用下面的 Polyfill 代替:
if (!Array.of) {
Array = function() {
return Array.prototype.slice.call(arguements);
};
}
slice method can also be called to convert Array-like objects / collections to a new Array. You just bind the method to the object. The arguments inside a function is an example of an 'array-like object'.
function list() { return Array.prototype.slice.call(arguments); } var list1 = list(1, 2, 3); // [1, 2, 3]
Array.from
能将一个拥有迭代器的对象(String,Set,Map,arguments等)转换为数组。不改变原对象,返回一个新数组。
语法:
三个参数。第一个为要转换的对象,必选;第二个为加工函数,可选;第三个为this
,可选;
一旦传入加工函数,则在函数内部必须明确返回值,否则数组成员将均为 undefined。
// 使用 Array.from() 输出从 0 到指定数字的数组 Array.from({length: 10}, (v, i) => i)
Array.isArray
在 ES5 提供该方法之前,用来判断数组的唯一可靠的方法恐怕只有这个了:
// 也是 Array.isArray 的 Polyfill
if (!Array.isArray){
Array.isArray = function(arg){
return Object.prototype.toString.call(arg) === '[object Array]';
};
}
toSource
返回数组源代码
forEach(fn, thisArg)
fn 表示在数组每一项上执行的函数,三个参数(value, index, arr)
thisArg 可选,用来当作 fn 函数内的 this 对象。
every
用传入的函数测试所有元素, 只要有一个函数返回 false,则结果为 false;若全部返回 true, 则结果为true。
some
用传入的函数测试所有元素,只要有一个函数返回 true, 则结果为 true;若全部返回 false, 则结果为 false 。
filter
用传入的函数测试所有元素,并返回所有通过测试的元素组成的新数组。相当于一个过滤器。
map
用传入的函数处理每个元素, 并返回由函数返回值组成的新数组。
reduce
/ reduceRight
接受一个方法作为累加器, 数组中的每个值(从左至右)开始合并, 最终为一个值。
arr.reduce(fn, initialValue)
entries
(ES6)
返回一个数组迭代器对象, 该对象包含数组中的每个索引的键值对。
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
(ES6)
返回第一个满足条件的元素 / 元素索引。
keys
(ES6)
返回一个数组索引的迭代器
var array = ["abc", "xyz"];
var iterator = array.keys();
console.log(iterator.next()); // Object {value: 0, done: false}
console.log(iterator.next()); // Object {value: 1, done: false}
console.log(iterator.next()); // Object {value: undefined, done: false}
values
(ES6)
返回一个数组迭代器对象,包含数组中每个索引对应的值。
var array = ["abc", "xyz"];
var iterator = array.values();
console.log(iterator.next().value);//abc
console.log(iterator.next().value);//xyz
Symbol.iterator
(ES6)
功能用法与values
一致
pop
删除一个数组或类数组对象中的最后一个元素,并返回该元素。
实现过程:
- Let O be the result of calling ToObject passing the this value as the argument.
- Let lenVal be the result of calling the [[Get]] internal method of O with argument "length".
- Let len be ToUint32(lenVal).
- If len is zero, a. Call the [[Put]] internal method of O with arguments "length", 0, and true. b. Return undefined.
- Else, len > 0 a. Let indx be ToString(len–1). b. Let element be the result of calling the [[Get]] internal method of O with argument indx. c. Call the [[Delete]] internal method of O with arguments indx and true. d. Call the [[Put]] internal method of O with arguments "length", indx, and true. e. Return element.
从实现过程中我们可以看出被pop
的不一定要是数组,类数组对象也是可以的。区别在于,若类数组对象中存在length
属性,则正常返回被删除元素;若类数组中没有length
属性,则返回undefined
,同时原对象中添加length: 0
键值对。
push
添加一个或多个元素到数组或类数组对象,返回数组新的长度。
同pop
一样,push
也可以对类数组对象进行操作。区别在于,若类数组对象中存在length
属性,则正常添加元素,同时将length
加 1 并返回;若数组中不存在length
属性,则将元素添加到索引为 0 的位置,设置length
的值为 1 并返回。
我们也经常用push
方法结合Function.prototypr.apply()
特性(第二个参数为参数数组,传值时一个一个传)进行数组的合并:
const arr1 = [1, 2, 3]
const arr2 = [4, 5, 6]
const arr3 = Array.prototype.push.apply(array, array2);
reverse
颠倒数组中元素的位置。返回对数组的引用。 若 length 属性小于 2 或 length 属性不为数值,则返回原数组。
shift
删除数组第一个元素,并返回这个元素。
同样受益于鸭式辩型,对于类数组对象,shift
同样可以处理;当类数组对象 length 属性不存在时则添加 length 属性且初始化为 0 。
sort
对数组进行排序,并返回数组。
语法: arr.sort([comparefn])
comparefn 可选。若省略, 则数组元素将按照各自转换为字符串的 Unicode 位点顺序排序。
同样适用于类数组对象,当类数组对象中无 length 属性时,不进行排序且不添加 length 属性。
需要注意的是,有时候排序结果在不同浏览器下表现不一致:
var array = [{ n: "a", v: 1 }, { n: "b", v: 1 }, { n: "c", v: 1 }, { n: "d", v: 1 }, { n: "e", v: 1 }, { n: "f", v: 1 }, { n: "g", v: 1 }, { n: "h", v: 1 }, { n: "i", v: 1 }, { n: "j", v: 1 }, { n: "k", v: 1 }, ];
array.sort(function (a, b) {
return a.v - b.v;
});
for (var i = 0,len = array.length; i < len; i++) {
console.log(array[i].n);
}
// f a c d e b g h i j k
可能会觉得有些奇怪,v 值均相同,那么结果为何和之前不一致? 这是因为在 V8 引擎中为了排序高效,数组长度超过 10 条时,会调用快排来排序,因此顺序就会被打乱;10条以下时采用插入排序。
splice
删除,新增或替换元素。
语法 : arr.splice(start, deleteCount[, item1[, item2[, ...]]])
start 指定从哪一位开始修改。负值时,指定的索引位置 = 负值 + 数组长度; deleteCount 指定要删除的元素个数。 itemN 指定新增元素,若缺省则只删除数组元素。
返回值为被删除元素组成的数组,若没有则返回一个空数组。
类数组中同样适用,若无 length 属性则添加并初始化为 0 。
unshift
用于在数组开始处添加元素,并返回数组新的长度。
copyWIthin
(ES6)
用于数组内元素之间的替换。
语法 : arr.copyWIthin(target, start[, end = this.length])
target 指定被替换元素的索引, start 指定替换元素起始的索引,end 可选,指的是替换元素结束位置的索引。
let arr1 = [1, 2, 3, 4, 5]
let arr2 = arr1.copyWithin(0, 3)
console.log(arr2 === arr1, arr2); // true [4, 2, 3, 1, 5]
fill
(ES6)
同样用于数组替换,不同的是可以指定替换元素,而copyWithin
只能用于数组内元素的互相替换。
语法: arr.fill(value, start[, end = this.length])
let arr1 = [1, 2, 3, 4, 5]
let arr2 = arr1.fill(10, 0, 3)
console.log(arr1 === arr2, arr2) // true [10, 10, 10, 4, 5]
concat
将传入的数组或元素与原数组合并,组成一个新的数组并返回。
join
将数组中的所有元素用参数连结成为字符串, 缺省值为逗号
slice
将数组中的一部分元素浅复制存入新的数组对象并返回这个数组对象。
传入参数为复制起始索引和结束索引
let arr = [1, 2, 3, 4, 5]
console.log(arr.slice(2, 3)) // [3]
toString
/ toLocaleString
返回数组的字符串形式。
indexOf
用于查找元素在数组中第一次出现时的索引,没有则返回 -1。使用 === 来匹配元素
lastIndexOf
查找元素在数组中最后一次出现时的索引,没有则返回 -1。为逆向查找。
includes
(ES7)
判断当前数组是否包含某个指定的值,是则返回 true, 否则返回 false。
include()
与indexOf()
的区别:
let arr = [NaN]
console.log(arr.includes(NaN)) // true
console.log(arr.indexOf(NaN)) // -1
参考文章: