JavaScript数组的特别之处(二):构造函数、空元素等

前言

上一篇文章已经多次提到,数组是一种特殊类型的对象,介绍了数组在类型、数组判断、索引值和length属性上的一些特性,而数组的这些特别之处很多都与对象有关。具体可见上篇博文JavaScript数组的特别之处(一)

另外,我们还需要知道的是,数组的索引虽然可以像对象一样,当做键名字符串使用,但它们还是有所区别的。数组是按照数字的顺序进行排列的集合,而对象的属性名则是无序的。所以上篇博文,我们使用特殊键名(如字符串、负数等)给数组赋值时,这些值都不是数组的元素。

除了之前介绍的这些特性之外,关于数组,还有一些不得不提的特别之处,本文将继续深入介绍,帮助我们更好的理解JavaScript中的数组。

创建数组的三种方式

当前JS中,创建数组大致有三种方式:数组字面量语法、Array构造函数、Array.of()。

数组字面量语法

字面量语法创建数组,是JavaScript中最常用的一种方式,由于方便简单,大部分代码都会使用它。

const arr1 = [] // 创建一个空数组
const arr2 = [1, 2, true, null, 'hello'] // 给定数组的元素
console.log(arr2) // [1, 2, true, null, 'hello']

以上代码,就是使用了字面量语法创建数组,如果不给元素值就会创建一个空数组。
需要了解的是,数组字面量语法其实也是基于对Array构造函数的一种简化使用。

Array构造函数

Array对象本身是JavaScript的一个内置对象,它是 function 类型,能当做构造函数使用,这与大多数内置对象一样,是否使用 new 操作符都可以。
因此,我们通过调用 Array()new Array(),就能创建数组对象。数组构造函数可以使用多种形式的可选参数,只不过依据参数不同,结果会有一定差异。

  1. 不传参数时,返回一个空数组
Array() // []
  1. 只传入一个参数时,表现不太一致
  • 当参数为0时,创建一个空数组
Array(0) // []
  • 当参数是单个正整数时,将创建一个length长度为该参数数值的数组,并且所有数组元素都是空位(返回undefined)
const arr = new Array(10)
arr.length // 10
arr[2] // undefined
  • 当参数是非正整数,如负数、小数等等,则会报错,无法创建数组
Array(10.6) // Uncaught RangeError: Invalid array length
Array(-6) // Uncaught RangeError: Invalid array length

以上代码,小数和负数,都报无效数组长度的错误。

但是,对于能自动转换成整数的数字(小数位为0),则可以正常创建数组,如下代码所示:

const arr = new Array(10.0)
arr.length // 10
arr[2] // undefined
  • 当参数是非数字的其他类型,如字符串值、布尔值、对象、数组、函数、null、undefined等等,则该参数将会成为新数组的第一个元素,数组的length长度自然就是1。
Array('hello') // ['hello']
Array(true) //[true]
Array([30]) // [Array(1)]
Array(null) // [null]
  • 只有一个参数的情况下,如果参数里多了尾逗号,则会忽略,仍能正常创建数组:
Array(0,) // []
Array(true,) // [true]
  1. 传入多个参数时

所有参数都会成为新数组的元素,不论参数是什么类型的值。

Array(1, 2) // [1, 2]
Array(1, 2, true, null, 'hello')  // [1, 2, true, null, 'hello']
Array(-1, 2.2, 3) // [-1, 2.2, 3]
Array(1, 2, 3,) // [1, 2, 3]

以上代码,
第三行,加了负数和小数,也能正常创建数组;
第四行,参数里多了一个尾逗号,但会被忽略。

Array.of()

Array.of(item…) 是ES6提供的一个数组静态方法,使用它同样可以创建数组。

该方法也提供了可选参数,但与Array构造函数的区别在于:Array.of() 的行为更一致,不论它的参数有几个、是什么类型,都会被当做新数组的元素成员,当然如果不传入参数,则会生成空数组。包括负数和小数,也都会被当成元素,不会报错。
比如,Array.of(5) 会创建只有一个成员(5)且长度为1的数组,而 Array(5) 则是创建一个长度为5且元素皆是空位的数组。

所以,Array.of方法弥补了Array构造函数参数差异导致的不足,除了字面量语法外,我们应该尽量用于替代Array构造函数。

Array.of() // []
Array.of(5) // [5]
Array.of(1, 2, true, null, 'hello') // [1, 2, true, null, 'hello']
Array.of(-1) // [-1]
Array.of(2.2, 0) // [2.2, 0]

从以上代码可以看出,当我们使用Array.of方法时,所有参数都作为了数组的元素,这可以完全解决Array构造函数带来的不一致问题。

空位(空元素)

空位是指数组中某个逗号前面,没有任何值,是空的,这样的元素就是空元素,又叫空位。
空位在JavaScript的数组中是允许存在的,并不会报语法错误或其他异常,数组能正常使用,所以我们需要了解它的一些特性。

逗号后面没有值,不产生空位,也不影响数组。

我们先看一个空位的示例:

const arr1 = [,]
const arr2 = [1, , , 4]

以上代码,就是空位在数组中的表现,其中arr1有1个空位,arr2在首尾两个元素中间有2个空位。

空位作为数组的一种特殊存在,它的一些基本表现如下:

  • 空位是数组的一个正常元素
  • 空位会被计算进数组的长度里,即length属性会包含空位
  • 空位可以通过索引读取,返回undefined。
const arr = [1, , , 4]
arr.length // 4
arr[2] // undefined

以上代码,定义了有2个空位的数组,数组长度不受影响,是4,读取空位值时返回undefined。

除了以上这些特点以外,空位还有其他一些需要注意的地方。

delete

delete运算符能够删除对象的属性,那么同样可在数组中使用它。
使用delete操作符删除数组元素的时候,就会产生空位,元素表现也符合空位的特点。

const arr = ['a', 'b', 'c']
delete arr[1]
console.log(arr) // ['a', , 'c']

以上代码,使用delete删除了数组的第二个元素,就在这个位置形成了一个空位。

循环遍历空位

空位是被当做一个正常的数组元素,并被计算在length属性里的,所以当我们遍历有空位的数组的时候,需要小心,不然会产生一些不必要的问题。

针对空位遍历时主要的一些注意点,总结如下:

  • for、while、for-of三个循环语句,都会正常遍历到空位,并输出空位的值为undefined。
  • for-in循环语句,则会直接跳过空位,不会遍历空位。
  • 数组的实例方法里面:
    • forEach、map、every、some、filter、reduce、flat,也都会直接跳过空位;
    • find、findIndex,则会读取到空位,返回undefined。
    • indexOf、lastIndexOf、includes,无法读取空位,因为空位啥也没有。
  • 当使用Object对象的keys、values、entries方法的时候,也是直接跳过空位。
const arr = [1, , , 4]
for (let i in arr) {
    
    
  console.log(i)
} // 跳过空位,输出为 '0' 和 '3'
for (let i of arr) {
    
    
  console.log(i)
} // 读取空位,输出为 1 undefined undefined 4

arr.forEach((vl) => {
    
    
  console.log(vl)
}) // 跳过空位,输出为 5 2

Object.keys(arr) // 也是跳过空位,输出为 ['0', '3']

以上代码,就是遍历时的部分示例,与上面总结的表现一致,for-of 能读取空位,其他如 for-inforEacheObject.keys 则直接跳过空位,不会遍历输出。

需要注意的是,空位在索引读取、或者部分语法访问的时候返回的undefined,但它并不等于undefined,空位所有的这些特点,undefined并没有。如果遍历的时候,undefined是数组元素的话,那它在任何情况下都能读取到。

数组空位的字符串输出

另外,当数组被当做字符串输出的时候,空位也有自己特有的输出。

  • 使用join() 和 toString() 方法的时候,空位元素输出只有一个逗号。
[1, , , 4].join() // '1,,,4'
[1, , , 4].toString() // '1,,,4'
  • 使用JSON.stringify() 方法的时候,空位输出为 null 字符串。
JSON.stringify([1, , , 4]) // '[1,null,null,4]'

in运算符

in运算符用于检查对象的某个属性键名是否存在,返回布尔值,数组属于对象,所以也能适用。
数组的键名就是索引值,我们使用数组索引值判断即可。

const arr = [1, 2, 3]
0 in arr // true
'2' in arr // true
3 in arr // false

以上代码,数组有三个元素,索引值0-2,而3并不属于、返回了false。
之前已有介绍对象键名是字符串,数组的索引值使用数字和字符串都没问题。

另外,就是对于数组中的空位,in运算符返回的是false:

const arr = [1, ,2]
0 in arr //true
1 in arr // false

以上代码,数组的第二个元素是空元素,那它使用 in 判断时,返回了false。

猜你喜欢

转载自blog.csdn.net/jimojianghu/article/details/128074182
今日推荐