数组对象是使用单独的变量名来存储一系列的值。
创建一个数组
- 常规方法
var myCarr=new Array();
myCarr[0] = "cat";
myCarr[1] = "dog";
myCarr[3] = "turkey";
- 简洁方式
var myPets=new Array("cat", "dog", "turkey");
var myPets = new Array(20); //创建一个长度为20的数组
-
字面
var myPets = ["cat", "dog", "turkey"]
访问数组
-
通过指定数组名以及索引号码,可以访问某个特定的元素。
var pet = myPets[0] //获取数组的第一个元素值 myPets[1] ="monkey" //给数组的第二个元素重新赋值
数组属性
- constructor 返回创建数组对象的原型函数
- length 设置或返回数组元素的个数
- prototype 允许你向数组对象添加属性或方法
Array对象的属性
-
数组合并/向数组中添加元素
-
concat()
连接两个或更多数组,并返回结果。var array = [1, 2, 3]; var arr1 = ["a","b", "c"]; array.concat(arr1) // [1, 2, 3,"a","b", "c"]
-
push()
向数组末尾添加一个或更多元素,并返回新的长度var array = [1,2,3]; array.push(7,8); // 5
-
unshift()
向数组的开头添加一个或更多元素,并返回新的长度var array = [1,2,3]; array.unshift("a", "b"); // 5
-
splice()
从数组中添加或删除元素var fruits = ["Banana", "Orange", "Apple", "Mango"]; fruits.splice(2,0,"Lemon","Kiwi"); // 2规定从何处添加/删除,0规定应该删除多少元素,如果不设置,则删除从index开始到原数组结尾的所有元素 console.log(fruits); //["Banana", "Orange","Lemon","Kiwi","Apple", "Mango"]
-
-
数组元素的删除
-
pop()
删除数组的最后一个元素并返回删除的元素var array = [1,2,3]; array.pop(); // 3
-
shift()
删除数组的第一个元素并返回该元素的值,数组中元素自动前移var fruits = ["Banana", "Orange", "Apple", "Mango"]; fruits.shift(); // Banana console.log(fruits); // ["Orange", "Apple","Mango"]
-
slice(start, end)
截取数组的一部分并返回一个新的数组(包含从start到end(不包括该元素))var fruits = ["Banana", "Orange", "Apple", "Mango"]; fruits.slice(1,3); // ["Orange", "Apple"]
-
-
copyWithin()
用于从数组指定位置拷贝元素到数组的另一个指定位置中var arr = ["Banana", "Orange", "Apple", "Mango",'dog','cat', 'monkey']; arr.copyWithin(2,0) // ["Banana", "Orange", "Banana", "Orange", "Apple", "Mango", "dog"]
语法: Array.copyWithin(target, start, end)
-
target
必需。复制到指定目标索引位置 -
start
必需。 元素复制的起始位置 -
end
可选。 停止复制的索引位置(默认为array.length)
-
-
every()
用于检测数组所有元素是否都符合指定条件var ages = [32, 33, 16, 40]; function checkAdult(age) { return age >= 18; } ages.every(checkAdult); //false
- 如果数组中检测到有一个元素不满足,则整个表达式返回
false
,且剩余的元素不会再进行检测。 - 如果所有元素都满足条件,则返回
true
- every()不会对空数组进行检测,并且不会改变原始数组
- 如果数组中检测到有一个元素不满足,则整个表达式返回
-
fill()
用于将一个固定值替换数组的元素语法:
array.fill(value, start, end)
-
value
必需。填充的值 -
start
可选。开始填充的位置 -
end
可选。停止填充的位置(默认为array.length)
var fruits = ["Banana", "Orange", "Apple", "Mango"]; fruits.fill("Runoob", 2, 4); // ["Banana", "Orange", "Runoob", "Runoob"]
-
-
filter()
创建一个新数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。不会对空数组进行检测,不会改变原始数组。var ages = [32, 33, 16, 40]; function checkAdult(age) { return age >= 18; } ages.filter(checkAdult); // [32,33,40]
-
find()
返回符合传入测试(函数)条件的数组元素该方法为数组中的每个元素都调用一次函数执行:
- 当数组中的元素满足测试条件时返回
true
,find()返回符合条件的元素,之后的值不会再调用执行函数 - 如果没有符合条件的元素,则返回
undefined
- 对于空数组,函数不会执行
- 该方法不会改变数组的原始值
var ages = [32, 33, 16, 40]; function checkAdult(age) { return age >= 18; } ages.find(checkAdult); // 32
- 当数组中的元素满足测试条件时返回
-
findIndex()
方法返回传入一个测试条件(函数)符合条件的数组第一个元素位置该方法为数组中的每个元素都调用一次函数执行:
- 当数组中的元素在测试条件返回
true
时,该方法返回符合条件的元素的索引位置,之后的值不会再调用执行函数。 - 如果没有符合条件的元素则返回-1
- 对于空数组,函数不会执行
- 该方法不会改变数组的原始值
var ages = [32, 33, 16, 40]; function checkAdult(age) { return age <= 18; } ages.findIndex(checkAdult); // 2
- 当数组中的元素在测试条件返回
forEach()
方法用于调用数组的每个元素,并将元素传递给回调函数-
indexOf()
方法可返回某个指定的字符串值在字符串中首次出现的位置。array.indexOf(item,start)
:-
item
必须。查找的元素 -
start
可选的整数参数。规定在字符串中开始检索的位置。它的合法取值是0到stringObject.length - 1。如省略该参数,则将从字符串的首字符开始检索。
-
lastIndexOf()
返回一个指定的字符串值最后出现的位置,在一个数组中的指定位置从后向前搜索。join
把数组的所有元素放入一个字符串map()
通过指定函数处理数组的每个元素,并返回处理之后的数组reduce()
方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。reduceRight()
方法的功能和 reduce() 功能是一样的,不同的是reduceRight() 从数组的末尾向前将数组中的数组项做累加。reverse()
反转数组的元素顺序some()
检测数组中是否有元素符合指定条件sort()
对数组元素进行排序toString()
把数组转换为字符串,并返回结果valueOf()
返回数组对象的原始值
扩展
- Array.of方法用于将一组值,转换为数组
Array.of(3, 11, 8) // [3,11,8]
Array.of(3) // [3]
Array.of(3).length // 1
这个方法的主要目的,是弥补数组构造函数Array()的不足。因为参数个数的不同,会导致Array()的行为有差异。
Array() // []
Array(3) // [, , ,]
Array(3, 11, 8) // [3, 11, 8]
- 数组实例的copyWithin()
数组实例的copyWithin方法,在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。也就是说,使用这个方法,会修改当前数组。
Array.prototype.copyWithin(target, start = 0, end = this.length)
它接受三个参数。
target(必需):从该位置开始替换数据。如果为负值,表示倒数。
start(可选):从该位置开始读取数据,默认为 0。如果为负值,表示倒数。
end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数。
这三个参数都应该是数值,如果不是,会自动转为数值。
[1, 2, 3, 4, 5].copyWithin(0, 3)
// [4, 5, 3, 4, 5]
-
Object.assign
方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)。
const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 };
Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}
Object.assign
方法的第一个参数是目标对象,后面的参数都是源对象。
注意,如果目标对象与源对象有同名属性,或多个源对象有同名属性,则后面的属性会覆盖前面的属性。
const target = { a: 1, b: 1 };
const source1 = { b: 2, c: 2 };
const source2 = { c: 3 };
Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}
注意点
(1)浅拷贝
Object.assign方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。
const obj1 = {a: {b: 1}};
const obj2 = Object.assign({}, obj1);
obj1.a.b = 2;
obj2.a.b // 2
上面代码中,源对象obj1的a属性的值是一个对象,Object.assign拷贝得到的是这个对象的引用。这个对象的任何变化,都会反映到目标对象上面。
(2)同名属性的替换
对于这种嵌套的对象,一旦遇到同名属性,Object.assign的处理方法是替换,而不是添加。
const target = { a: { b: 'c', d: 'e' } }
const source = { a: { b: 'hello' } }
Object.assign(target, source)
// { a: { b: 'hello' } }
上面代码中,target对象的a属性被source对象的a属性整个替换掉了,而不会得到{ a: { b: 'hello', d: 'e' } }的结果。这通常不是开发者想要的,需要特别小心。
一些函数库提供Object.assign的定制版本(比如 Lodash 的_.defaultsDeep方法),可以得到深拷贝的合并。
(3)数组的处理
Object.assign可以用来处理数组,但是会把数组视为对象。
Object.assign([1, 2, 3], [4, 5])
// [4, 5, 3]
上面代码中,Object.assign把数组视为属性名为 0、1、2 的对象,因此源数组的 0 号属性4覆盖了目标数组的 0 号属性1。
(4)取值函数的处理
Object.assign只能进行值的复制,如果要复制的值是一个取值函数,那么将求值后再复制。
const source = {
get foo() { return 1 }
};
const target = {};
Object.assign(target, source)
// { foo: 1 }
上面代码中,source对象的foo属性是一个取值函数,Object.assign不会复制这个取值函数,只会拿到值以后,将这个值复制过去。
常见用途
Object.assign方法有很多用处。
(1)为对象添加属性
class Point {
constructor(x, y) {
Object.assign(this, {x, y});
}
}
上面方法通过Object.assign方法,将x属性和y属性添加到Point类的对象实例。
(2)为对象添加方法
Object.assign(SomeClass.prototype, {
someMethod(arg1, arg2) {
···
},
anotherMethod() {
···
}
});
// 等同于下面的写法
SomeClass.prototype.someMethod = function (arg1, arg2) {
···
};
SomeClass.prototype.anotherMethod = function () {
···
};
上面代码使用了对象属性的简洁表示法,直接将两个函数放在大括号中,再使用assign方法添加到SomeClass.prototype之中。
(3)克隆对象
function clone(origin) {
return Object.assign({}, origin);
}
上面代码将原始对象拷贝到一个空对象,就得到了原始对象的克隆。
不过,采用这种方法克隆,只能克隆原始对象自身的值,不能克隆它继承的值。如果想要保持继承链,可以采用下面的代码。
function clone(origin) {
let originProto = Object.getPrototypeOf(origin);
return Object.assign(Object.create(originProto), origin);
}
(4)合并多个对象
将多个对象合并到某个对象。
const merge =
(target, ...sources) => Object.assign(target, ...sources);
如果希望合并后返回一个新对象,可以改写上面函数,对一个空对象合并。
const merge =
(...sources) => Object.assign({}, ...sources);
(5)为属性指定默认值
const DEFAULTS = {
logLevel: 0,
outputFormat: 'html'
};
function processContent(options) {
options = Object.assign({}, DEFAULTS, options);
console.log(options);
// ...
}
上面代码中,DEFAULTS对象是默认值,options对象是用户提供的参数。Object.assign方法将DEFAULTS和options合并成一个新对象,如果两者有同名属性,则option的属性值会覆盖DEFAULTS的属性值。
注意,由于存在浅拷贝的问题,DEFAULTS对象和options对象的所有属性的值,最好都是简单类型,不要指向另一个对象。否则,DEFAULTS对象的该属性很可能不起作用。
const DEFAULTS = {
url: {
host: 'example.com',
port: 7070
},
};
processContent({ url: {port: 8000} })
// {
// url: {port: 8000}
// }
上面代码的原意是将url.port改成 8000,url.host不变。实际结果却是options.url覆盖掉DEFAULTS.url,所以url.host就不存在了。
- flat() 用于将嵌套的数组“拉平”,变成一维的数组。该方法返回一个新数组,对原数据没有影响。
[1, 2, [3, 4]].flat()
// [1, 2, 3, 4]
上面代码中,原数组的成员里面有一个数组,flat()方法将子数组的成员取出来,添加在原来的位置。
flat()默认只会“拉平”一层,如果想要“拉平”多层的嵌套数组,可以将flat()方法的参数写成一个整数,表示想要拉平的层数,默认为1。
上面代码中,flat()的参数为2,表示要“拉平”两层的嵌套数组。
如果不管有多少层嵌套,都要转成一维数组,可以用Infinity关键字作为参数。
[1, [2, [3]]].flat(Infinity) // [1, 2, 3]
如果原数组有空位,flat()方法会跳过空位。
[1, 2, , 4, 5].flat() // [1, 2, 4, 5]