你真的了解Array对象吗

前言
数组是我们平时编码中必不可少的一个重要,无论是数据的处理还是数据的传递,它都起到了至关重要的作用。无论是老版的JavaScript还是ES6都提供了大量的方法让我们来对数组进行处理。本文主要介绍Array对象的本质和它的相关属性,方法。
Array
原型链示意图

分两个方向来分析Array
1 JavaScript的原生对象Array
1-1 Array有哪些属性和方法。
按f12打开控制台输入【Array. 】你会发现侧边出现了很长的一串的属性和方法的补全提示,这些属性和方法到底哪些是可用的又有哪些是Array对象本身的呢?我们可以试验一下。

console.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对象的属性和方法。

console.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

1-2 属性和方法使用
1-2-1 length属性返回Array对象的长度。
这里的length属性只是Array本身的length属性,其值为1。
1-2-2 name属性返回Array对象名称。
与length属性一样,其值为”Array”。
1-2-3 form方法,转换其它类型的数据并返回一个新的数组。
参数1:要转换的数据

将类数组对象转换为真正数组:
let 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结构的数据转换为真正的数组: 
let arr = [1,2,3,4,5,5,6]
let set = new Set(arr);
console.log(Array.from(set));
// [1,2,3,4,5,6]

将字符串转换为数组:返回分割字符串形成的数组。
let str = ‘foo’;
console.log(Array.from(str));
// [“f”,”o”,”o”]

Array.from参数是一个真正的数组:返回原数组。
console.log(Array.from([1,2,3,4,5]))
// [1,2,3,4,5]

参数2:回调函数
let arr = [1, 2, 3, 4, 5];
console.log(Array.from(arr, item => item + 1));
// [2,3,4,5,6];
1-2-4 isArray方法用于判断一个对象是否为数组。
let arr = [1,2,3];
let str = “123”;
let num = 123;
Array.isArray(arr);
Array.isArray(str);
Array.isArray(num);
// 打印结果
true
false
false
1-2-5 of方法用于创建一个新的数组。
let arr = Array.of(1);
let arr2 = Array.of(2);
let arr3 = Array.of(1,2,3,4);
//
[1]
[5]
[1,2,3,4]
注意:form和of都是ES6新增的方法。
2 作为函数调用
2-1 规范
当数组作为函数调用而不是构造函数调用时,它会创建并初始化一个新的数组对象。因此当Array(…)和new Array(…)接收同样的参数时,它们是相同的。
let arr = Array(1,3);
// [1,3];
let arrs = new Array(1,3);
// [1,3];
2-2 传参

传入多个数值或者多个其它类型的数据的时候,直接以【,】分割这些数据形成一个新的数组。
let arrStr = new Array(“1”, “2”);
//[“1″,”2”]
let arrObj = new Array({name: “csz”}, {“age”: 12});
//[{name: “csz”}, {age: 12}]

传入一个 0 到 232-1 之间的整数,会把它识别为创建的数组的长度,会创建一个这个以这个整数位长度,每一项都是undefined的数组。
let arr = new Array(3);
console.log(arr[0], arr[1], arr.length);
// undefined, undefined, 3

ES6新增的of方法没有第二种传参方式。

2-3 实例方法
不管是通过字面量还是new Array亦或者是Array.of()创建的实例对象,它们的__proto__属性都是指向了Array的原型对象,就继承了原型对象上的属性和方法。
ES5原有方法 Array.prottotype.
2-3-1 forEach()
数组调用该方法,每一个元素执行callback一次。
2个参数:

callback 接受3个参数。

currentValue,数组中正在处理的当前元素。
index,数组中正在处理的当前元素的索引。
array,forEach方法被调用的数组。

thisArg

执行callback函数时使用的this 值。
如果thisArg参数有值,则每次 callback 函数被调用的时候,this 都会指向 thisArg 参数上的这个对象。如果省略了 thisArg 参数,或者赋值为 null 或 undefined,则 this 指向全局对象。

let 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]
2-3-2 shift()
方法从数组中删除第一个元素,并返回该元素的值。此方法更改原有数组。
let arr = [1, 2, 3];
console.log(arr.shift()); // 1
console.log(arr); // [2,3]
2-3-3 pop()
方法从数组中删除最后一个元素,并返回该元素的值。此方法更改原有数组。
let arr = [1, 2, 3];
console.log(arr.pop()); // 3
console.log(arr); // [1,2]
2-3-4 unshift()
方法将一个或多个元素添加到数组的开头,并返回该数组的新长度。此方法更改原有数组。
一个参数
elementN 要添加到数组开头的元素。
let arr = [1, 2, 3];
console.log(arr.unshift(4, 5)); // 5
console.log(arr); // [4,5,1,2,3]
2-3-5 push()
方法将一个或多个元素添加到数组的末尾,并返回该数组的新长度。此方法更改原有数组。
一个参数
elementN 要添加到数组开头的元素。
let arr = [1, 2, 3];
console.log(arr.push(4, 5)); // 5
console.log(arr); // [1,2,3,4,5]
2-3-6 splice()
方法通过删除现有元素和/或添加新元素来修改数组,并以数组返回原数组中被修改的元素。此方法更改原有数组。
3个参数:

start​指定修改的开始位置(从0计数)。如果超出了数组的长度,则从数组末尾开始添加内容;如果是负值,则表示从数组末位开始的第几位(从-1计数);如果负数的绝对值大于数组的长度,则表示开始位置为第0位。

deleteCount

整数,表示要移除的数组元素的个数。
如果 deleteCount 是 0或者负数,则不移除元素。这种情况下,至少应添加一个新元素。
如果 deleteCount 大于start 之后的元素的总数,则从 start 后面的元素都将被删除(含第 start 位)。
如果deleteCount被省略,则其相当于(arr.length – start)。

item1, item2, …要添加进数组的元素,从start 位置开始。如果不指定,则 splice() 将只删除数组元素。

let 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]
2-3-7 slice()
方法通起止索引截取数组中的元素,返回一个新的数组对象。原始数组不会被改变。
2个参数:

start​

指定截取的开始位置(从0计数)。如果该参数为负数,则表示从原数组中的倒数第几个元素开始提取。
省略就从0开始截取。
没有end就从开始位置截取,剩下的所有数组中的元素。

end

在该索引处结束提取原数组元素(从0开始)。
slice会提取原数组中索引从 begin 到 end 的所有元素(包含begin,但不包含end)。

let 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]
2-3-8 join()方法
将一个数组的所有元素按指定分隔符连接成一个字符串并返回这个字符串,不改变原数组。
一个参数

separator

指定一个字符串来分隔数组的每个元素。
默认为 “,”。
如果separator是空字符串(“”),则所有元素之间都没有任何字符。

let arr = [1, 3, 4];
console.log(arr.join(“”)); // “134”
console.log(arr.join(“-“)); // “1-3-4”
// “1”;
2-3-9 reverse()
方法将数组中元素的位置颠倒。改变原数组。
let arr = [1,2,3,4,5];
console.log(arr.reverse()); // [5, 4, 3, 2, 1]
console.log(arr) // [5, 4, 3, 2, 1]
2-3-10 concat()方法
用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组。
let arr = [1, 3, 4];
let arr1 = [1, 2, “a”];
console.log(arr.concat(arr1));
// [1,3,4,1,2,”a”];
2-3-11 indexOf()方法
返回在数组中可以找到给定元素的第一个索引,如果不存在,则返回-1。
2个参数:

searchElement 要查找的元素。

fromIndex

开始查找的位置。默认为0
-1代表数组中的最后一个元素,依次为起点往前查找。

let arr = [1, 2, 3];
console.log(arr.indexOf(1)); // 0
console.log(arr.indexOf(5)); // -1
2-3-12 lastIndexOf()方法
返回指定元素在数组中的最后一个的索引,如果不存在则返回 -1。从数组的后面向前查找,从传参的索引处开始。
2个参数:

searchElement 要查找的元素。

fromIndex

从此位置开始逆向查找。默认为数组的长度减 1,即整个数组都被查找。
如果该值大于或等于数组的长度,则整个数组会被查找。如果为负值,将其视为从数组末尾向前的偏移。
即使该值为负,数组仍然会被从后向前查找。如果该值为负时,其绝对值大于数组长度,则方法返回 -1,即数组不会被查找。

let arr = [1, 2, 3, 1];
console.log(arr.lastIndexOf(1, 0)); // 3
console.log(arr.lastIndexOf(1, 2)); // 0
2-3-13 toString()
返回一个数组元素组成的字符串,以逗号分隔。不改变原数组。
let arr = [1, 2, 3];
console.log(arr.toString()); // “1,2,3”
console.log(arr); // [1, 2, 3]
2-3-14 map()
数组调用该方法,callback会循环遍历数组一次,最后返回一个每一次循环遍历处理后的结果组成的新数组。不会改变原有数组。
2个参数:

callback 接受3个参数。

currentValue,数组中正在处理的当前元素。
index,数组中正在处理的当前元素的索引。
array,map方法被调用的数组。

thisArg

执行callback函数时使用的this 值。
如果thisArg参数有值,则每次 callback 函数被调用的时候,this 都会指向 thisArg 参数上的这个对象。如果省略了 thisArg 参数,或者赋值为 null 或 undefined,则 this 指向全局对象。

let 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参数时,不要使用箭头函数。
2-3-15 every()
方法测试数组的所有元素是否都通过了指定函数的测试。全部通过返回true, 否则返回false。
2个参数:

callback 用来测试每个元素的函数,接受3个参数。

currentValue,数组中正在处理的当前元素。
index,数组中正在处理的当前元素的索引。
array,every方法被调用的数组。
遍历数组的每一个元素执行callback,只要有一个元素在执行callback的时候return false,every方法停止执行返回false。

thisArg 执行 callback 时使用的 this 值。(使用方法用map()一致)

let 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
2-3-16 some()
方法测试数组中的某些元素是否通过由提供的函数实现的测试。有一个通过返回true, 全部不通过返回false。
2个参数:

callback 用来测试每个元素的函数,接受3个参数。

currentValue,数组中正在处理的当前元素。
index,数组中正在处理的当前元素的索引。
array,every方法被调用的数组。
遍历数组的每一个元素执行callback,只要有一个元素在执行callback的时候return true,every方法停止执行返回true。

thisArg 执行 callback 时使用的 this 值。(使用方法用map()一致)

let arr = [1, 3, 5, 7, 9, 21, 2, 4, 6];
console.log(arr.some((v, i, array) => {
return v > 10;
}));
// true
2-3-17 filter()
方法创建一个新数组, 其包含通过所提供函数实现的测试的所有元素。
2个参数:

callback 用来测试每个元素的函数,接受3个参数。

currentValue,数组中正在处理的当前元素。
index,数组中正在处理的当前元素的索引。
array,filter方法被调用的数组。
遍历数组的每一个元素执行callback,把满足条件的元素返回最后集合组成一个新的数组。

thisArg 执行 callback 时使用的 this 值。(使用方法用map()一致)

let 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新增方法 Array.prottotype.
2-3-18 includes()方法
用来判断一个数组是否包含一个指定的值,根据情况,如果包含则返回 true,否则返回false。
2个参数:

searchElement 需要查找的元素值。-
fromIndex 从该索引处开始查找 searchElement。如果为负值,则按升序从 array.length – fromIndex 的索引开始搜索。默认为 0。

let arr = [1, 2, 3];
console.log(arr.includes(1)); // true
console.log(arr.includes(5)); // false
2-3-19 find()
方法返回数组中满足提供的测试函数的第一个元素的值。否则返回 undefined。
2个参数:

callback 用来测试每个元素的函数,接受3个参数。

currentValue,数组中正在处理的当前元素。
index,数组中正在处理的当前元素的索引。
array,find方法被调用的数组。
遍历数组的每一个元素执行callback,返回第一个满足条件的元素。

thisArg 执行 callback 时使用的 this 值。(使用方法用map()一致)

let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
let newArr = arr.find((v, i, array) => {
return v > 5;
});
console.log(newArr);
// 6
2-3-20 findIndex()
方法返回数组中满足提供的测试函数的第一个元素的索引。否则返回-1。
2个参数:

callback 用来测试每个元素的函数,接受3个参数。

currentValue,数组中正在处理的当前元素。
index,数组中正在处理的当前元素的索引。
array,findIndex方法被调用的数组。
遍历数组的每一个元素执行callback,返回第一个满足条件的元素的索引。

thisArg 执行 callback 时使用的 this 值。(使用方法用map()一致)

let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
let newArr = arr.findIndex((v, i, array) => {
return v > 5;
});
console.log(newArr);
// 5
2-3-21 fill()
方法用一个固定值填充一个数组中从起始索引到终止索引内的全部元素。不包括终止索引。改变原数组。
3个参数:

start 用来填充数组元素的值。
start 起始索引,默认值为0。
end 终止索引,默认值为 this.length。

let arr = [1, 2, 3, 4, 5, 6];
arr.fill(“csz”, 1, 4);
console.log(arr);
// [1, “csz”, “csz”, “csz”, 5, 6]
还有几个方法相关介绍我还没有理的很清楚,这里先不贴了。等后续会加上。

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理