前言
数组是我们平时编码中必不可少的一个重要,无论是数据的处理还是数据的传递,它都起到了至关重要的作用。无论是老版的JavaScript还是ES6都提供了大量的方法让我们来对数组进行处理。本文主要介绍Array对象的本质和它的相关属性,方法。
Array原型图
原型链示意图
分两个方向来分析
原生对象Array
作为JavaScript的原生对象Array
属性和方法
按f12打开控制台输入
Array.
你会发现侧边出现了很长的一串的属性和方法的补全提示,这些属性和方法到底哪些是可用的又有哪些是Array对象
本身的呢?我们可以试验一下。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17console.log(Array.length);
console.log(Array.name);
console.log(Array.from);
console.log(Array.isArray);
console.log(Array.of);
console.log(Array.apply);
console.log(Array.bind);
console.log(Array.constructor);
console.log(Array.toString);
console.log(Array.hasOwnProperty);
console.log(Array.isPrototypeOf);
console.log(Array.toLocaleString);
console.log(Array.valueOf);
console.log(Array.arguments);
console.log(Array.call);
console.log(Array.caller);打印结果
除了最后的3个属性报错其他的属性或方法全部被打印出来,但是这些不一定就是
Array
的本身的属性和方法。首先Array
可以作为函数实例对象
实际上可以看做是通过new Function()
创建的,所以它继承了Function原型对象
上的属性和方法,而Function.prototype
作为对象是可以继承Object原型对象
上的属性和方法。所以Array
也继承了Object
原型对象上的属性和方法。我们可以通过Object的hasOwnProperty方法来判断哪些才是真正的属于Array对象的属性和方法。
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
27console.log(Array.hasOwnProperty("length"));
console.log(Array.hasOwnProperty("name"));
console.log(Array.hasOwnProperty("from"));
console.log(Array.hasOwnProperty("isArray"));
console.log(Array.hasOwnProperty("of"));
console.log(Array.hasOwnProperty("apply"));
console.log(Array.hasOwnProperty("bind"));
console.log(Array.hasOwnProperty("constructor"));
console.log(Array.hasOwnProperty("toString"));
console.log(Array.hasOwnProperty("hasOwnProperty"));
console.log(Array.hasOwnProperty("isPrototypeOf"));
console.log(Array.hasOwnProperty("toLocaleString"));
console.log(Array.hasOwnProperty("valueOf"));
//打印结果
true
true
true
true
true
false
false
false
false
false
false
false
false通过上面的分析我们知道了
Array
作为对象其实只拥有length
,name
两个属性和form
,isArray
,of
这3个方法。注意:这里还有几个继承的方法和属性我没有一一列举出来更多属性可见详情[Array][4]
属性和方法使用
length属性
返回Array
对象的长度。这里的length
属性只是Array
本身的length
属性,其值为1。
name属性
返回Array
对象名称。与length
属性一样,其值为Array
。
form方法
转换其它类型的数据并返回一个新的数组。
- 参数1:要转换的数据
- 用法:
将类数组对象转换为真正数组
1
2
3
4
5
6
7
8
9let fakeArray = {
0: "csz",
1: "women",
2: "21",
3: ["say","sleep","drink"],
'length': 4
}
console.log(Array.from(fakeArray))
// ["csz", "women", "21", ["say","sleep","drink"]]注意:要将一个类数组对象转换为一个真正的数组,必须具备以下条件:
- 该类数组对象必须具有
length
属性,用于指定数组的长度。如果没有length
属性,那么转换后的数组是一个空数组。 - 该类数组对象的属性名必须为数值型或字符串型的数字。如果不是转成的数组的值全是
undefined
。
- 该类数组对象必须具有
用法:将
Set
结构的数据转换为真正的数组:1
2
3
4let arr = [1,2,3,4,5,5,6]
let set = new Set(arr);
console.log(Array.from(set));
// [1,2,3,4,5,6]用法:将字符串转换为数组:返回分割字符串形成的数组。
1
2
3let str = 'foo';
console.log(Array.from(str));
// ["f","o","o"]用法:
Array.from
参数是一个真正的数组:返回原数组。1
2console.log(Array.from([1,2,3,4,5]))
// [1,2,3,4,5]
- 参数2:回调函数
- 用法:
1
2
3
let arr = [1, 2, 3, 4, 5];
console.log(Array.from(arr, item => item + 1));
// [2,3,4,5,6];
isArray方法
用于判断一个对象是否为数组。
- 参数1:要判断的数据
- 用法:
1 | let arr = [1,2,3]; |
of方法
用于创建一个新的数组。
- 参数1:创建的数据的元素
- 用法:
1 | let arr = Array.of(1); |
注意:form
和of
都是ES6
新增的方法。
函数Array
作为构造函数调用或者普通函数调用。
规范
当数组作为函数调用而不是构造函数调用时,它会创建并初始化一个新的数组对象。因此当Array(...)
和new Array(...)
接收同样的参数时,它们是相同的。1
2
3
4let arr = Array(1,3);
// [1,3];
let arrs = new Array(1,3);
// [1,3];
传参
传入多个数值或者多个其它类型的数据的时候,直接以【,】分割这些数据形成一个新的数组。
1
2
3
4let arrStr = new Array("1", "2");
//["1","2"]
let arrObj = new Array({name: "csz"}, {"age": 12});
//[{name: "csz"}, {age: 12}]传入一个
0
到232-1
之间的整数,会把它识别为创建的数组的长度,会创建一个这个以这个整数位长度,每一项都是undefined
的数组。1
2
3let arr = new Array(3);
console.log(arr[0], arr[1], arr.length);
// undefined, undefined, 3ES6新增的
of
方法没有第二种传参方式。
实例方法(ES5)
不管是通过字面量还是new Array
亦或者是Array.of()
创建的实例对象,它们的__proto__
属性都是指向了Array
的原型对象,就继承了原型对象上的属性和方法。
Array.prototype.
forEach()方法
- 两个参数:
callback
接受3个参数。currentValue
,数组中正在处理的当前元素。index
,数组中正在处理的当前元素的索引。array
,forEach
方法被调用的数组。
thisArg
- 执行
callback
函数时使用的this
值。 - 如果
thisArg
参数有值,则每次callback
函数被调用的时候,this
都会指向thisArg
参数上的这个对象。如果省略了thisArg
参数,或者赋值为null
或undefined
,则this
指向全局对象。
- 执行
- 用法:数组调用该方法,每一个元素执行
callback
一次。1
2
3
4
5
6
7
8
9
10
11let arr = [1, 2, 3];
arr.forEach(function (v, i, arr) {
console.log(v);
arr.push(1);
});
console.log(arr);
// 打印结果
1
2
3
[1,2,3,1,1,1]
shift()
- 参数:无。
- 用法:方法从数组中删除第一个元素,并返回该元素的值。此方法更改原有数组。
1
2
3let arr = [1, 2, 3];
console.log(arr.shift()); // 1
console.log(arr); // [2,3]
pop()
- 参数:无。
- 用法:方法从数组中删除最后一个元素,并返回该元素的值。此方法更改原有数组。
1
2
3let arr = [1, 2, 3];
console.log(arr.pop()); // 3
console.log(arr); // [1,2]
unshift()
- 一个参数
elementN
要添加到数组开头的元素。
- 用法:方法将一个或多个元素添加到数组的开头,并返回该数组的新长度。此方法更改原有数组。
1
2
3let arr = [1, 2, 3];
console.log(arr.unshift(4, 5)); // 5
console.log(arr); // [4,5,1,2,3]
push()
- 一个参数
elementN
要添加到数组开头的元素。
- 用法:方法将一个或多个元素添加到数组的末尾,并返回该数组的新长度。此方法更改原有数组。
1
2
3let arr = [1, 2, 3];
console.log(arr.push(4, 5)); // 5
console.log(arr); // [1,2,3,4,5]
splice()
- 三个参数
start
指定修改的开始位置(从0计数)。如果超出了数组的长度,则从数组末尾开始添加内容;如果是负值,则表示从数组末位开始的第几位(从-1计数);如果负数的绝对值大于数组的长度,则表示开始位置为第0
位。deleteCount
- 整数,表示要移除的数组元素的个数。
- 如果
deleteCount
是0
或者负数,则不移除元素。这种情况下,至少应添加一个新元素。 - 如果
deleteCount
大于start
之后的元素的总数,则从start
后面的元素都将被删除(含第start
位)。 - 如果
deleteCount
被省略,则其相当于(arr.length - start
)。
item1, item2, ...
要添加进数组的元素,从start
位置开始。如果不指定,则splice()
将只删除数组元素。
- 用法:方法通过删除现有元素和/或添加新元素来修改数组,并以数组返回原数组中被修改的元素。此方法更改原有数组。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24let arr = [1, 2, 3, 4, 5];
// start超过数组长度,且没有添加新的元素
console.log(arr.splice(5)); //[]
console.log(arr); //[1,2,3,4,5]
// start不超过数组长度,且没有添加新的元素
let arr1 = [1, 2, 3, 4, 5];
console.log(arr1.splice(0, 2)); //[1,2]
console.log(arr1); //[3,4,5]
// start不超过数组长度,删除个数为0或者负数,添加新的元素
let arr2 = [1, 2, 3, 4, 5];
console.log(arr2.splice(0, 0, 1)); // []
console.log(arr2); // [1,1,2,3,4,5]
// start为负数且负数绝对值不超过数据长度,添加新的元素
let arr3 = [1, 2, 3, 4, 5];
console.log(arr3.splice(-3, 1, "a")); //[3]
console.log(arr3); //[1,2,"a",4,5]
// start为负数且负数绝对值超过数据长度,添加新的元素
let arr4 = [1, 2, 3, 4, 5];
console.log(arr4.splice(-6, 1, "a")); //[3]
console.log(arr4); //["a",2,3,4,5]
slice()
- 两个参数:
start
- 指定截取的开始位置(从
0
计数)。如果该参数为负数,则表示从原数组中的倒数第几个元素开始提取。 - 省略就从
0
开始截取。 - 没有
end
就从开始位置截取,剩下的所有数组中的元素。
- 指定截取的开始位置(从
end
- 在该索引处结束提取原数组元素(从
0
开始)。 slice
会提取原数组中索引从begin
到end
的所有元素(包含begin
,但不包含end
)。
- 在该索引处结束提取原数组元素(从
- 用法:方法通起止索引截取数组中的元素,返回一个新的数组对象。原始数组不会被改变。
1
2
3
4
5
6
7
8
9
10
11
12
13
14let arr = [1, 2, 3, 4, 5];
// start为正数,没有end
console.log(arr.slice(1)); //[2,3,4,5]
console.log(arr); //[1,2,3,4,5]
let arr1 = [1, 2, 3, 4, 5];
// start为正数,有end
console.log(arr1.slice(1, 3)); //[2,3]
console.log(arr1); //[1,2,3,4,5]
let arr2 = [1, 2, 3, 4, 5];
// 两个参数都是负数
console.log(arr2.slice(-3, -1)); //[3,4]
console.log(arr2); //[1,2,3,4,5]
join()方法
- 一个参数
eparator
- 指定一个字符串来分隔数组的每个元素。
- 默认为
,
。 - 如果
separator
是空字符串""
,则所有元素之间都没有任何字符。
- 用法:将一个数组的所有元素按指定分隔符连接成一个字符串并返回这个字符串,不改变原数组。
1
2
3
4let arr = [1, 3, 4];
console.log(arr.join("")); // "134"
console.log(arr.join("-")); // "1-3-4"
// "1";
reverse() 方法
- 参数:无。
- 用法:方法将数组中元素的位置颠倒。改变原数组。
1
2
3let arr = [1,2,3,4,5];
console.log(arr.reverse()); // [5, 4, 3, 2, 1]
console.log(arr) // [5, 4, 3, 2, 1]
concat()方法
- 参数:无。
- 用法:用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。
1
2
3
4let arr = [1, 3, 4];
let arr1 = [1, 2, "a"];
console.log(arr.concat(arr1));
// [1,3,4,1,2,"a"];
indexOf()方法
- 两个参数:
searchElement
要查找的元素。fromIndex
- 开始查找的位置。默认为
0
-1
代表数组中的最后一个元素,依次为起点往前查找。
- 开始查找的位置。默认为
- 用法:返回在数组中可以找到给定元素的第一个索引,如果不存在,则返回
-1
。1
2
3let arr = [1, 2, 3];
console.log(arr.indexOf(1)); // 0
console.log(arr.indexOf(5)); // -1
lastIndexOf()方法
- 两个参数:
searchElement
要查找的元素。fromIndex
- 从此位置开始逆向查找。默认为数组的长度减
1
,即整个数组都被查找。 - 如果该值大于或等于数组的长度,则整个数组会被查找。如果为负值,将其视为从数组末尾向前的偏移。
- 即使该值为负,数组仍然会被从后向前查找。如果该值为负时,其绝对值大于数组长度,则方法返回
-1
,即数组不会被查找。
- 从此位置开始逆向查找。默认为数组的长度减
- 用法:返回指定元素在数组中的最后一个的索引,如果不存在则返回
-1
。从数组的后面向前查找,从传参的索引处开始。1
2
3let arr = [1, 2, 3, 1];
console.log(arr.lastIndexOf(1, 0)); // 3
console.log(arr.lastIndexOf(1, 2)); // 0
toString()方法
- 参数:无。
用法:返回一个数组元素组成的字符串,以逗号分隔。不改变原数组。
1
2
3let arr = [1, 2, 3];
console.log(arr.toString()); // "1,2,3"
console.log(arr); // [1, 2, 3]
map()方法
- 两个参数:
callback
接受3个参数。currentValue
,数组中正在处理的当前元素。index
,数组中正在处理的当前元素的索引。array,map
方法被调用的数组。
thisArg
- 执行
callback
函数时使用的this
值。 - 如果
thisArg
参数有值,则每次callback
函数被调用的时候,this
都会指向thisArg
参数上的这个对象。如果省略了thisArg
参数,或者赋值为null
或undefined
,则this
指向全局对象。
- 执行
用法:数组调用该方法,
callback
会循环遍历数组一次,最后返回一个每一次循环遍历处理后的结果组成的新数组。不会改变原有数组。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19let obj = {
name: 'csz',
say: function () {
console.log(this.name);
}
}
let arr = [1, 2];
let map1 = arr.map(function (value, index, array) {
console.log(value, index, array);
this.say();
return value = value + 2;
}, obj);
console.log(map1, arr);
// 打印结果
1 0 [1, 2]
csz
2 1 [1, 2]
csz
[3, 4] [1, 2]因为箭头函数内的this指向是保持不变的,所以当要使用thisArg参数时,不要使用箭头函数。
every()
- 两个参数:
callback
用来测试每个元素的函数,接受3个参数。currentValue
,数组中正在处理的当前元素。index
,数组中正在处理的当前元素的索引。array,every
方法被调用的数组。- 遍历数组的每一个元素执行
callback
,只要有一个元素在执行callback
的时候return false
,every
方法停止执行返回false
。
hisArg
执行callback
时使用的this
值。(使用方法用map()
一致)
- 用法:方法测试数组的所有元素是否都通过了指定函数的测试。全部通过返回
true
, 否则返回false
。1
2
3
4
5
6
7
8
9
10
11let arr = [1, 3, 5, 7, 9, 10];
let arr1 = [1, 3, 5, 7];
console.log(arr.every((v, i, array) => {
return v % 2 !== 0;
}));
console.log(arr1.every((v, i, array) => {
return v % 2 !== 0;
}));
// 打印结果
false
true
some()
- 两个参数:
callback
用来测试每个元素的函数,接受3个参数。currentValue
,数组中正在处理的当前元素。index
,数组中正在处理的当前元素的索引。array,every
方法被调用的数组。- 遍历数组的每一个元素执行
callback
,只要有一个元素在执行callback
的时候return true
,every
方法停止执行返回true
。
thisArg
执行callback
时使用的this
值。(使用方法用map()
一致)
- 用法:方法测试数组中的某些元素是否通过由提供的函数实现的测试。有一个通过返回
true
, 全部不通过返回false
。1
2
3
4
5let arr = [1, 3, 5, 7, 9, 21, 2, 4, 6];
console.log(arr.some((v, i, array) => {
return v > 10;
}));
// true
filter()
- 两个参数:
callback
用来测试每个元素的函数,接受3个参数。currentValue
,数组中正在处理的当前元素。index
,数组中正在处理的当前元素的索引。array
,filter
方法被调用的数组。- 遍历数组的每一个元素执行
callback
,把满足条件的元素返回最后集合组成一个新的数组。
thisArg
执行callback
时使用的this
值。(使用方法用map()
一致)
- 方法:方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。
1
2
3
4
5
6let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
let newArr = arr.filter((v, i, array) => {
return v % 2 === 0;
});
console.log(newArr);
// [2,4,6,8]
实例方法(ES6)
不管是通过字面量还是new Array
亦或者是Array.of()
创建的实例对象,它们的__proto__
属性都是指向了Array
的原型对象,就继承了原型对象上的属性和方法。
Array.prototype.
includes()方法
- 两个参数:
searchElement
需要查找的元素值。-fromIndex
从该索引处开始查找searchElement
。如果为负值,则按升序从array.length - fromIndex
的索引开始搜索。默认为0
。
- 用法:用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回
true
,否则返回false
。1
2
3let arr = [1, 2, 3];
console.log(arr.includes(1)); // true
console.log(arr.includes(5)); // false
find()方法
- 两个参数:
callback
用来测试每个元素的函数,接受3个参数。currentValue
,数组中正在处理的当前元素。index
,数组中正在处理的当前元素的索引。array,find
方法被调用的数组。- 遍历数组的每一个元素执行
callback
,返回第一个满足条件的元素。
thisArg
执行callback
时使用的this
值。(使用方法用map()
一致)
- 用法:方法返回数组中满足提供的测试函数的第一个元素的值。否则返回
undefined
。1
2
3
4
5
6let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
let newArr = arr.find((v, i, array) => {
return v > 5;
});
console.log(newArr);
// 6
findIndex()方法
- 两个参数:
callback
用来测试每个元素的函数,接受3个参数。currentValue
,数组中正在处理的当前元素。index
,数组中正在处理的当前元素的索引。array
,findIndex
方法被调用的数组。- 遍历数组的每一个元素执行
callback
,返回第一个满足条件的元素的索引。
thisArg
执行callback
时使用的this
值。(使用方法用map()
一致)
- 用法:方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回
-1
。1
2
3
4
5
6let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
let newArr = arr.findIndex((v, i, array) => {
return v > 5;
});
console.log(newArr);
// 5
fill()方法
方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引。改变原数组。
- 三个参数:
start`
用来填充数组元素的值。start
起始索引,默认值为0。end
终止索引,默认值为this.length
。
- 用法
1
2
3
4let arr = [1, 2, 3, 4, 5, 6];
arr.fill("csz", 1, 4);
console.log(arr);
// [1, "csz", "csz", "csz", 5, 6]
还有几个方法相关介绍我还没有理的很清楚,这里先不贴了。等后续会加上…