JS 数组常见问题

70 阅读3分钟

数组

数组深拷贝和浅拷贝

浅拷贝

  1. Object.assign([拷贝参数])
  2. 递归实现
  3. 扩展运算符
const demo = {
      name: 'Tom',
      age: 18,
      family: [
            {name: 'mama'},
            {name: 'baba'}
      ]
}
// 第一层是深拷贝,修改demo2不会影响demo,但是修改family的值会影响demo
const demo2 = {...demo}
  1. slice() (仅适用于数组):

slice() : 返回一个新数组,这一对象是一个由 start 和 end 决定的原数组的浅拷贝, 左开右闭([start,end)

// 基本数据类型,slice实现基本数据类型深拷贝,修改arr1不会影响arr
const arr = [1,2,3,4]
const arr1 = arr.slice()
// 数组元素非基本数据类型,是浅拷贝,修改arr3会影响arr2
const arr2 = [{name: 'Tom'},{name: 'Marry'}]
const arr3 = arr2.slice()
  1. concat()

concat : 用于合并两个或多个数组。此方法不会更改现有数组,而是返回一个新数组

// 基本数据类型,concat实现基本数据类型深拷贝,修改arr1不会影响arr
const arr = [1,2,3,4]
const arr1 = arr.concat()
// 数组元素非基本数据类型,是浅拷贝,修改arr3会影响arr2
const arr2 = [{name: 'Tom'},{name: 'Marry'}]
const arr3 = arr2.concat()

深拷贝

  1. 使用 JSON :
    • 步骤:JSON.stringify() 将对象或数组转为JSON字符串;JSON.parse() 将JSON字符串解析为Object类型。
    • 限制:
      • 它不能正确处理包含循环引用的对象。
      • 它不能正确复制特殊对象,如Date、RegExp和函数。
      • 它会丢失原始对象的原型链信息。
  2. Lodash_.cloneDeep 方法
  3. 递归函数实现:

hasOwnProperty() : 返回一个布尔值,表示对象自有属性(而不是继承来的属性)中是否具有指定的属性

const demo = {
      name: 'Tom',
      age: 18,
      family: [
            {name: 'mama'},
            {name: 'baba'}
      ]
}
function deepClone(obj) {
      // 判断是否是对象
      if (typeof obj !== 'object') return
      // 判断是数组还是对象
      let newObj = Array.isArray(obj) ? [] : {}
      for (let key in obj) {
            // 判断是否有该属性
            if (obj.hasOwnProperty(key)) {
                  newObj[key] =
                        typeof obj[key] === 'object'
                              ?
                              deepClone(obj[key])
                              :
                              obj[key]
            }
      }
      return newObj
}
const demo1 = deepClone(demo)

如何判断一个数组

在 JavaScript 中,要判断一个变量是否是数组,你可以使用以下几种方法:

  1. 使用Array.isArray()方法:

    if (Array.isArray(variable)) {
      // 变量是一个数组
    } else {
      // 变量不是一个数组
    }
    

    这是最常用的方法,因为它是 JavaScript 内置的,能够准确地检测一个值是否是数组。

  2. 使用instanceof操作符:

    if (variable instanceof Array) {
      // 变量是一个数组
    } else {
      // 变量不是一个数组
    }
    

    这种方法也可以用来检测一个对象是否是数组,但需要注意,如果变量是在不同的 JavaScript 上下文(比如不同的窗口或帧)中创建的,instanceof可能会产生错误的结果。

  3. 使用Object.prototype.toString.call()方法:

    if (Object.prototype.toString.call(variable) === '[object Array]') {
      // 变量是一个数组
    } else {
      // 变量不是一个数组
    }
    

    这种方法是比较底层的方式,通过检查变量的内部[[Class]]属性来确定其类型。虽然不太常用,但也是一种可靠的方法。

一般来说,推荐使用Array.isArray()方法,因为它更简单、清晰,而且能够准确地检测变量是否是数组。