除了Object
之外,Array
类型恐怕是 ECMAScript
中最常用的类型了。而且,ECMAScript
中的数组与其他多数语言中的数组有着相当大的区别。虽然ECMAScript
数组与其他语言中的数组都是数据的有序列表,但与其他语言不同的是,ECMAScript
数组的每一项可以保存任何类型的数据。也就是说,可以用数组的第一个位置来保存字符串,用第二位置来保存数值用第三个位置来保存对象,以此类推。而且,ECMAScript
数组的大小是可以动态调整的,即可以随着数据的添加自动增长以容纳新增数据。
创建数组
1.1 使用 Array 构造函数
有三种方式来调用构造函数:
- 调用时没有参数,该方法创建一个没有任何元素的空数组,等同于[]。
let animals = new Array();
- 调用时有一个数值参数,用于指定长度,而该参数会自动变成
length
属性的值, 下面的代码将创建length
值为 10 的数组:
let animals = new Array(10);
- 直接向
Array
构造函数传递数组中应该包含的项,构造函数的参数将成为新数组的元素。
let animals = new Array("cat", "dog", "pig");
另外,在使用
Array
构造函数时也可以省略new
操作符。如下面的例子所示,省略new
操作符的结果相同:
let animals = Array(3); // 创建一个包含 3 项的数组
let names = Array("pig"); // 创建一个包含 1 项,即字符串"pig"的数组
1.2 使用数组字面量表示法
数组字面量由一对包含数组项的方括号表示,多个数组项之间以逗号隔开。
如下所示:
let animals = ["pig", "dog", "cat"]; // 创建一个包含 3 个字符串的数组
let names = []; // 创建一个空数组
let values = [1,2,]; // 这样会创建一个包含 2 或 3 项的数组
let count = [1,,3]; //数组有三个元素,中间那个值为undefined
let options = [,,,,,]; // 这样会创建一个包含 5 或 6 项的数组
数组元素的读和写
在读取和设置数组的值时,要使用方括号并提供相应值的基于的数字索引,方括号中的索引表示要访问的值。
let animals = ["pig", "dog", "cat"]; // 定义一个字符串数组
alert(animals[0]); // 显示第一项
animals[2] = "black"; // 修改第三项
animals[3] = "brown"; // 新增第四项
数组的项数保存在其 length
属性中,这个属性始终会返回 0 或更大的值:
let animals = ["pig", "dog", "cat"]; // 创建一个包含 3 个字符串的数组
let names = []; // 创建一个空数组
alert(animals.length); //3
alert(names.length); //0
可以利用数组中的length
属性从数组的末尾移除项或向数组中添加新项:
let animals = ["pig", "dog", "cat"]; // 创建一个包含 3 个字符串的数组
animals.length = 2;
alert(animals[2]); //undefined
这个例子中的数组 animals
一开始有3个值。将其length
属性设置为2会移除最后一项(位置为2 的那一项),结果再访问 animals[2]
就会显示 undefined
.
如果将其 length
属性设置为大于数组项数的值,则新增的每一项都会取得 undefined
值:
let animals = ["pig", "cat", "dog"]; // 创建一个包含 3 个字符串的数组
animals.length = 4;
alert(animals[3]); //undefined
在此,虽然 animals
数组包含3个项,但把它的length
属性设置成了4。这个数组不存在位置 3,所以访问这个位置的值就得到了特殊值 undefined
。
利用 length
属性也可以方便地在数组末尾添加新项:
let animals = ["red", "blue", "green"]; // 创建一个包含 3 个字符串的数组
animals[animals.length] = "tigger"; //(在位置 3)添加一种动物
animals[animals.length] = "brid"; //(在位置 4)再添加一种动物
由于数组最后一项的索引始终是length-1
,因此下一个新项的位置就是length
。每当在数组末尾添加一项后,其 length
属性都会自动更新:
let animals = ["pig", "cat", "dog"]; // 创建一个包含 3 个字符串的数组
animals[99] = "brid"; // 在位置99的索引上添加一种动物
alert(animals.length); // 100
检测数组
用于确定某个对象是不是数组。
- 使用
instanceof
操作符
if (animals instanceof Array){
//对数组执行某些操作
}
instanceof
运算符其实用来判断一个构造函数的prototype
属性所指向的对象是否存在另外一个要检测对象的原型链上。
instanceof
操作符的问题在于,它假定只有一个全局执行环境。如果网页中包含多个框架,那实际上就存在两个以上不同的全局执行环境,从而存在两个以上不同版本的Array
构造函数。如果你从一个框架向另一个框架传入一个数组,那么传入的数组与在第二个框架中原生创建的数组分别具有各自不同的构造函数。
- 使用
Array.isArray()
方法
if (Array.isArray(value)){
//对数组执行某些操作
}
数组方法
数组的转换方法
- 在
javascript
中所有对象都具有toLocaleString()
、toString()
和valueOf()
方法。
其中,调用数组的 toString()
方法会返回由数组中每个值的字符串形式拼接而成的一个以逗号分隔的字符串。
而调用 valueOf()
返回的还是数组。实际上,为了创建这个字符串会调用数组每一项的 toString()
方法。
let colors = ["red", "blue", "green"]; // 创建一个包含 3 个字符串的数组
console.log(colors.toString()); // red,blue,green
console.log(colors.valueOf()); // ["red","blue","green"]
console.log(colors); // red,blue,green
console.log(typeof(colors.toString()));// string
console.log(typeof(colors.valueOf())); //object
console.log(Array.isArray(colors.valueOf())); //true
toLocaleString()
方法经常也会返回与 toString()
方法相同的值。在默认情况是是调用 totring()
,只有当toLocalString()
方法的值和toString()
的值不一样的情况下才会出现不一样的结果。
let obj1 = {
toLocaleString : function () {
return "小黄瓜1";
},
toString : function() {
return "小嗨瓜1";
}
};
let obj2 = {
toLocaleString : function () {
return "小黄瓜2";
},
toString : function() {
return "小嗨瓜2";
}
};
let people = [obj1, obj2];
console.log(people); //小黄瓜1,小黄瓜2
console.log(people.toString()); //小黄瓜1,小黄瓜2
console.log(people.toLocaleString()); //小嗨瓜1,小嗨瓜2
数组继承的
toLocaleString()
、toString()
和valueOf()
方法,在默认情况下都会以逗号分隔的字符串的形式返回数组项,不改变原数组。
Array.join()
方法
可以使用不同的分隔符来构建这个字符串。join()
方法只接收一个参数,即用作分隔符的字符串,然后返回包含所有数组项的字符串。
let animal = ["dog", "pig", "cat"];
alert(animal.join(",")); //dog,pig,cat
alert(animal.join("||")); //dog||pig||cat
如果不给
join()
方法传入任何值,或者给它传入 undefined,则使用逗号作为分隔 符。
通过join()
方法可以实现重复字符串,只需传入字符串以及重复的次数,就能返回重复后的字符串:
function mark(str , n){
return new Array(n + 1).join(str);
}
console.log(mark("小黄瓜" , 4)); //小黄瓜小黄瓜小黄瓜小黄瓜
console.log(mark("小嗨瓜" , 3)); //小嗨瓜小嗨瓜小嗨瓜
不改变原数组,返回包含所有数组项的字符串。
Array.from()
方法(ES6)
将类(伪)数组对象或可遍历对象转换为真数组。
let arr =Array.of(3,4,5,'小黄瓜','li');
console.log(arr); //[3, 4, 5, '小黄瓜',"li"]
//字符串转数组
let str = "huanggua";
console.log(Array.from(str)); //Array(5) ["h","u","a","n","g","g","u","a"]
//将类数组对象转换为真正数组:
let arrList = {
0: 'xiao',
1: '22',
2: '男',
3: ['xiao','huang','gua'],
4: 5,
'length': 5
}
let arr = Array.from(arrList)
console.log(arr) // Array(4) ['xiao','22','男',['xiao','huang','gua'],5]
//1、该类数组对象必须具有length属性,用于指定数组的长度。如果没有length属性,那么转换后的数组是一个空数组
//2、该类数组对象的属性名必须为数值型或字符串型的数字
let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
};
// ES5的写法
let arr1 = [].slice.call(arrayLike); // ['a', 'b', 'c']
// ES6的写法
let arr2 = Array.from(arrayLike); // ['a', 'b', 'c']
Array.of()
方法(ES6)
将一组值,转成数组。
let arr = Array.of('apple','banana','orange');
console.log(arr); //['apple','banana','orange']
数组元素的添加和删除
Array.push()
方法可以接收任意数量的参数,把它们逐个添加到数组末尾。
let animals = new Array(); // 创建一个数组
let count = animals.push("pig", "dog"); // 推入两项
console.log(count); //2
count = animals.push("cat"); // 推入另一项
console.log(count); //3
console.log(animals) //["pig","dog","cat"]
push() 方法返回修改后数组的长度,改变原数组。
Array.pop()
方法则从数组末尾移除最后一项,减少数组的length
值。
let animals = ["pig","dog","cat"];
let item = animals.pop(); // 删除最后一项
console.log(item); //"cat"
console.log(animals.length); //2
console.log(animals); //["pig","dog"]
pop() 方法返回移除的项,改变原数组。
Array.shift()
方法,它能够移除数组中的第一个项,同时将数组长度减 1。
let animals = ["pig","dog","cat"];
let item = animals.shift(); //取得第一项
console.log(item); //"pig"
console.log(animals.length); //2
console.log(animals);//["dog","cat"]
shift() 方法返回移除的项,改变原数组。
Array.unshift()
方法,它能在数组前端添加任意个项。
let animals = ["pig","dog","cat"];
let count = colors.unshift("brid", "trigger");
console.log(count); //5
console.log(animals); //["brid", "trigger","pig","dog","cat"];
unshift() 方法返回新数组的长度,改变原数组。
数组的排序方法
Array.reverse()
方法会反转数组项的顺序。
let colors = [1, 2, 3, 4, 5];
colors.reverse();
alert(colors); //5,4,3,2,1
reverse() 方法会改变原数组,返回值是经过排序之后的数组。
Array.sort()
方法按升序排列数组项——即最小的值位于最前面,最大的值排在最后面。sort()
方法会调用每个数组项的toString()
转型方法,然后比较得到的字符串,以 确定如何排序。
let colors = [0, 1, 5, 10, 15];
colors.sort();
alert(colors); //0,1,10,15,5
sort()
方法也会根据测试字符串的结果改变原来的顺序。
因为数值 5 虽然小于 10,但在进行字符串比较时,"10"则位于"5"的前面,于是数组的顺序就被修改。
因此 sort()
方法可以接收一个比较函数作为参数,以便我们指定哪个值位于哪个值的前面。比较函数接收两个参数,如果第一个参数应该位于第二个之前则返回一个负数,如果两个参数相等则返回 0,如果第一个参数应该位于第二个之后则返回一个正数。以下就是一个简单的比较函数:
a. 升序排序:
function compare(value1,value2){
if(value1 < value2){
return -1;
}else if(value1 > value2){
return 1;
}else{
return 0
}
}
let colors = [1,2,3,5,4,7];
colors.sort(compare);
console.log(colors); //[1,2,3,4,5,7]
对于数值类型或者其 valueOf()
方法会返回数值类型的对象类型也可以写成:
function compare(value1,value2){
return value1 - value2;
//降序:value2 - value1
}
b. 按照数组对象中的某个属性值进行排序:
let arr:[
{name:"小黄瓜" , age:"22"},
{name:"小绿瓜" , age:"12"},
{name:"小红瓜" , age:"44"},
]
function compare(option){
return function(value1,value2){
let obj1 = value1[option];
let obj2 = value2[option];
return obj1 - obj2;
}
}
arr.sort(compare("age"));
sort() 方法会改变原数组,返回值是经过排序之后的数组。
数组的合并方法
Array.concat()
方法
这个方法会先创建当前数组一个副本,然后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组。在没有给 concat()
方法传递参数的情况下,它只是复制当前数组并返回副本。如果传递给 concat()
方法的是一或多个数组,则该方法会将这些数组中的每一项都添加到结果数组中。如果传递的值不是数组,这些值就会被简单地添加到结果数组的末尾。
let animals = ["pig", "dog", "cat"];
let animals2 = animals.concat("brid", ["trigger", "panda"]);
console.log(animals); //[pig,dog,cat]
console.log(animals2); //[pig,dog,cat,brid,trigger,panda]
返回合并后的新数组,不改变原数组。
...
扩展运算符 ES6中的解构赋值方法
let animals1 = ["pig", "dog", "cat"];
let animals2 = ["trigger", "panda"];
let animals3 = [...animals1 , ...animals2];
console.log(animals3); //["pig", "dog", "cat","trigger", "panda"]
数组的截取
Array.slice()
方法
接受一或两个参数,即要返回项的起始和结束位置。在只有一个参数的情况下,slice()
方法返回从该
参数指定位置开始到当前数组末尾的所有项。如果有两个参数,该方法返回起始和结束位置之间的项—
—但不包括结束位置的项。
let animals = ["pig","dog","cat","brid","trigger","panda"];
let animals2 = animals.slice(1);
let animals3 = animals.slice(1,4);
console.log(animals2); //dog,cat,brid,trigger,panda
console.log(animals3); //dog,cat,brid
返回截取的数组,不改变原数组。
数组的操作方法
Array.splice()
方法
splice()
方法的用法:
-
删除:可以删除任意数量的项,只需指定 2 个参数:要删除的第一项的位置和要删除的项数。 例如,
splice(0,2)
会删除数组中的前两项。 -
插入:可以向指定位置插入任意数量的项,只需提供 3 个参数:起始位置、0(要删除的项数) 和要插入的项。如果要插入多个项,可以再传入第四、第五,以至任意多个项。例如,
splice(2,0,"pig","dog")
会从当前数组的位置 2 开始插入字符串"pig"
和"dog"
。 -
替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,只需指定 3 个参数:起 始位置、要删除的项数和要插入的任意数量的项。插入的项数不必与删除的项数相等。例如,
splice (2,1,"pig","dog")
会删除当前数组位置 2 的项,然后再从位置 2 开始插入字符串"pig"
和"dog"
。
//删除
let animals = ["pig", "dog", "cat"];
let newAnimals = animals.splice(0,1); // 删除第一项
console.log(animals); // dog, cat
console.log(newAnimals); // pig,返回的数组中只包含一项
//插入
let animals = ["pig" , "dog" , "cat"];
let newAnimals = animals.splice(1, 0, "brid", "panda"); // 从位置 1 开始插入两项
console.log(animals); // pig,brid,panda,dog,cat,
console.log(newAnimals); // 返回的是一个空数组
//替换
let animals = ["pig" , "dog", "cat"];
let newAnimals = animals.splice(1, 1, "red", "purple"); // 插入两项,删除一项
console.log(animals); // pig,red,purple,cat
console.log(newAnimals); // dog,返回的数组中只包含一项
fill()
方法(ES6)
填充, 参数替换原数组内容,但是会改变原来的数组。
参数:
该方法有三个参数:
fill(value, start, end)
value:想要替换的内容。
start:开始位置(数组的下标),可以省略。
end:替换结束位置(数组的下标),如果省略不写就默认为数组结束。
//1、只传入一个值(替换的内容),那将覆盖所有数组内的内容
let animals = ["dog", "cat", "pig", "brid"];
animals.fill("panda");
//panda,panda,panda,panda
//2、传入三个参数(替换的内容,起始位置,结束位置),那将把填充值替换到起始位置和结束位置之间
let animals = ["dog", "cat", "pig", "brid"];
animals.fill("panda", 2, 4);
//dog,cat,panda,panda
返回修改后的数组,改变原数组。
Array.copyWithin()
方法
操作当前数组自身,用来把某些个位置的元素复制并覆盖到其他位置。
该函数有三个参数。
target:目的起始位置。
start:复制源的起始位置,可以省略,可以是负数。
end:复制源的结束位置,可以省略,可以是负数,实际结束位置是end-1。
let arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
let newArr = arr.copyWithin(1, 3, 6); //将4,5,6复制覆盖到1下标的位置
console.log(newArr); //[1,4,5,6,5,6,7,8,9,10,11]
返回值为复制覆盖后的新数组,改变原数组。
数组的位置方法
Array.indexOf()
方法
返回要查找的项在数组中的位置,或者在没找到的情况下返回-1。接受两个参数:要查找的项和(可选的)表示查找起点位置的索引。
Array.lastIndexOf()
方法
从数组的末尾开始向前查找
let numbers = [1,2,3,4,5,4,3,2,1];
console.log(numbers.indexOf(4)); //3
console.log(numbers.lastIndexOf(4)); //5
console.log(numbers.indexOf(4, 4)); //5
console.log(numbers.lastIndexOf(4, 4)); //3
let person = { name: "Nicholas" };
let people = [{ name: "Nicholas" }];
let morePeople = [person];
console.log(people.indexOf(person)); //-1
console.log(morePeople.indexOf(person)); //0
返回查找到的下标,不会改变原数组。
find()
方法(ES6)
查找数组内元素,找到第一个符合条件的数组成员,返回该成员的值,如果没有找到,返回
undefined
。
例子:
let arr = [0,1,2,3,4,5];
let result = arr.find(function(item, index, Array){
return item > 1; // 查找第一个大于1的值
})
console.log(result); // 2
findIndex()
方法(ES6)
查找数组内元素,找到第一个符合条件的数组成员,返回该成员的下标
(index)
, 没找到返回-1。
let arr = ["xiao", "huang", "gua"];
let result = arr.findIndex(function(item, index, Array){
return item == "gua"; // 查找到的字符串为gua的下标
})
console.log(result); // 2
Array.includes()
方法
查找数组内是否包含指定的元素, 返回一个布尔值。
该方法的第二个参数表示搜索的起始位置,默认为0。如果第二个参数为负数,则表示倒数的位置。
let arr = [1, 2, 3, 4, 5, 6]
let newArr = arr.includes(3); //查找数组中是否包含元素3
console.log(newArr); //true
let arr = [1, 2, 3, 4, 5, 6]
let newArr = arr.includes(3,3); //从下标3开始查找数组中是否包含元素3
console.log(newArr); //false
返回值为true或false,不会影响原数组。
数组的迭代方法
参数:
每个方法都接收两个参数:要在每一项上运行的函数和(可选的)运行该函数的作用域对象——影响 this
的值。传入这些方法中的函数会接收三个参数:数组项的值、该项在数组中的位置和数组对象本身。
every()
方法
对数组中的每一项运行给定函数,如果该函数对每一项都返回
true
,则返回true
。(每一项都返回true,才返回true
)。
let numbers = [1,2,3,4,5,4,3,2,1];
let everyResult = numbers.every(function(item, index, array){
return (item > 2);
});
console.log(everyResult); //false
some()
方法
对数组中的每一项运行给定函数,如果该函数对任一项返回
true
,则返回true
。(有一项返回true
,就返回true
)。
let numbers = [1,2,3,4,5,4,3,2,1];
let everyResult = numbers.some(function(item, index, array){
return (item > 2);
});
console.log(everyResult); //true
filter()
方法(过滤)
对数组中的每一项运行给定函数,返回该函数会返回
true
的项组成的数组。
let numbers = [1,2,3,4,5,4,3,2,1];
let everyResult = numbers.filter(function(item, index, array){
return (item > 2);
});
console.log(everyResult); //[3,4,5,4,3]
map()
方法(映射)
对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。
let numbers = [1,2,3,4,5,4,3,2,1];
let everyResult = numbers.map(function(item, index, array){
return (item > 2);
});
console.log(everyResult); //[false, false, true, true, true, true, true, false, false][3,4,5,4,3]
let numbers = [1,2,3,4,5,4,3,2,1];
let everyResult = numbers.map(function(item, index, array){
return (item * 2);
});
console.log(everyResult); //[2, 4, 6, 8, 10, 8, 6, 4, 2]
map()方法创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。返回值是一个新的数组。
forEach()
方法(遍历)
对数组中的每一项运行给定函数。这个方法没有返回值。
let numbers = [1,2,3,4,5,4,3,2,1];
numbers.forEach(function(item, index, array){
//执行某些操作
});
forEach() 方法对数组的每个元素执行一次提供的函数。总是返回undefined。
for...in
方法(遍历下标,无序)
//使用for...in遍历数组,得到下标
let numbers = [1,2,3,4,5,6];
for(item in numbers){
console.log(item)
} //0,1,2,3,4,5
//使用for...in遍历对象,得到对象的key值
let numbers = {name:"小黄瓜" , age:"22"};
for(item in numbers){
console.log(item)
} //name , age
for...of
方法(循环)(ES6)
let numbers = [1,2,3,4,5];
for(let item of numbers){
console.log(item)
} //1,2,3,4,5
总结:for in总是得到对像的key或数组,字符串的下标,而for of和forEach一样,是直接得到值, forof不能在对象中使用。
数组的归并方法
参数:
- 这两个方法都接收两个参数:一个在每一项上调用的函数和(可选的)作为归并基础的初始值。
- 传给
reduce()
和reduceRight()
的函数接收4个参数:前一个值、当前值、项的索引和数组对象。这个函数返回的任何值都会作为第一个参数自动传给下一项。第一次迭代发生在数组的第二项上,因此第一个参数是数组的第一项,第二个参数就是数组的第二项。
reduce()
方法
从数组的第一项开始,逐个遍历到最后,累加数组的所有项,然后构建一个最终返回的值。
//数组求和
let numbers = [1,2,3,4,5];
let sum = numbers.reduce(function(prev, cur, index, array){
return prev + cur;
});
console.log(sum); //15
//第一次执行回调函数,prev 是 1,cur 是 2。
reduceRight()
方法
从数组的最后一项开始,向前遍历到第一项
let numbers = [1,2,3,4,5];
let sum = numbers.reduceRight(function(prev, cur, index, array){
return prev + cur;
});
console.log(sum); //15
//第一次执行回调函数,prev 是 5,cur 是 4。
使用 reduce()还是 reduceRight(),主要取决于要从哪头开始遍历数组。除此之外,它们完全 相同。
总结
会改变原数组的方法:
Array.shift():删除数组第一个元素。返回值为被删除的元素。
Array.unshift():向数组的第一个位置添加元素。返回值为数组的长度。
Array.pop():删除数组中最后一个元素。返回值为被删除的元素。
Array.push():向数组中最后一位添加元素。返回值为数组的长度。
Array.sort():数组排序。返回值为排序后的新数组。
Array.reverse():反转数组中的元素。返回值为反转后的新数组。
Array.splice():添加或删除数组元素。返回值为被删除的元素。
fill():(ES6)数组填充。返回值为修改后的数组。
Array.copyWithin():(ES6)复制覆盖元素。返回值为复制覆盖后的新数组。
不会改变原数组的方法:
Array.slice():截取数组中的元素。返回值为被截取元素组成的新数组。
Array.concat():合并数组元素。返回值为元素合并后的新数组。
Array.join():数组转字符串。返回转化后的字符串。
toString():数组转字符串。返回转化后的字符串。
toLocaleString():数组转字符串。返回转化后的字符串。
indexOf():查找数组是否存在某个元素。返回查找到的下标。
lastIndexOf():倒序查找数组是否存在某个元素。返回查找到的下标。
Array.includes():(ES6)查找数组中是否包含指定元素。返回true或false。
遍历方法:
every():判断数组中的元素是否全都满足条件。返回true或false。
some():判断数组中是否有满足条件的元素。返回true或false。
forEach():遍历。无返回值。
filter():根据条件进行过滤,返回新数组。
map():映射,对数组中的每个元素进行处理,返回新数组。
reduce():数组的归并,将元素归并为一个值。
reduceRight():从右向左进行归并。
find():(ES6)根据条件查找数组元素。
findIndex():(ES6)根据条件查找数组元素下标。
后记
断断续续接近三天的时间 ,终于将数组的相关方法和用法相对全面的整理了一下,没想到平时没用到的还有这么多方法,其实仔仔细细的对数组的方法全部过一遍还是能发现好多不一样的东西的。
下一篇: javascript对象
本文参考: