JavaScript数组对象

数组对象是使用单独的变量名来存储一系列的值。

创建一个数组

  • 常规方法
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]

你可能感兴趣的:(JavaScript数组对象)