14 JavaScript References VS Copying

效果

14 JavaScript References VS Copying_第1张图片
效果图

Demo
Github

知识点

  • 数组的复制
    • arr.slice()
    • [].concat(arr)
    • Array.from(arr)
    • [...arr]
  • 对象的复制
    • Object.assign({}, obj, {x: xx})
    • JSON.parse(JSON.stringify(obj))

笔记

在复制 Array 和 Object 类型数据的时候,不能通过直接赋值的办法,如下:

// Array
const arr1 = ['a', 'b', 'c', 'd']
const arr2 = arr1

console.log(arr1, arr2)  // ['a', 'b', 'c', 'd'], ['a', 'b', 'c', 'd']

arr2[2] = 'x'

console.log(arr1, arr2)  // ['a', 'b', 'x', 'd'], ['a', 'b', 'x', 'd']
// Object
const obj1 = {
  name: '令狐冲',
  age: 31
}
const obj2 = obj1

console.log(obj1, obj2)  // {name: '令狐冲', age: 31}, {name: '令狐冲', age: 31}

obj2.name = '任盈盈'

console.log(obj1, obj2)  // {name: '任盈盈', age: 31}, {name: '任盈盈', age: 31}

这样的结果显然不是我们想要的,原因就是在 JavaScript 中直接将对象赋值给变量,只是对它的引用,类似于 C 语言中的指针,为了应对这种特性,我们有以下几种解决办法:

拷贝数组

  • 方法一
    const arr1 = ['a', 'b', 'c', 'd']
    
    // 利用 slice() 方法返回一个新数组,而不会改变原数组
    const arr2 = arr1.slice()
    
  • 方法二
    // 利用 concat() 方法,以一个空数组拼接原数组
    const arr3 = [].concat(arr1)
    
  • 方法三
    // 利用 ES6 提供的新方法 Array.from(),创建新数组
    const arr4 = Array.from(arr1)
    
  • 方法四
    // 利用扩展语句
    const arr5 = [...arr1]
    
    但是展开语法有个问题,就是它只能做拷贝一层的浅拷贝,比如:
    const item1 = ['a', 'b', 'c', [1, 2, 3]]
    const item2 = [...item1]
    
    console.log(item1)  // ['a', 'b', 'c', [1, 2, 3]]
    console.log(item2)  // ['a', 'b', 'c', [1, 2, 3]]
    
    item2[1] = 'x'
    console.log(item1)  // ['a', 'b', 'c', [1, 2, 3]]
    console.log(item2)  // ['a', 'x', 'c', [1, 2, 3]]
    
    item2[3][1] = 'oo'
    console.log(item1)  // ['a', 'b', 'c', [1, 'oo', 3]]
    console.log(item2)  // ['a', 'x', 'c', [1, 'oo', 3]]
    

拷贝对象

  • 方法一
    // 使用 Object.assign() 方法
    const obj1 = { name: '令狐冲', age: 31 }
    const obj2 = Object.assign({}, obj1)
    
    const obj3 = Object.assign({}, obj1, {'剑法': '独孤九剑', '内功': '易筋经'})
    
    console.log(obj1)  // { name: '令狐冲', age: 31 }
    console.log(obj2)  // { name: '令狐冲', age: 31 }
    console.log(obj3)  // { name: '令狐冲', age: 31, '剑法': '独孤九剑', '内功': '易筋经' }
    
    但是,此方法如同数组的展开语法一样,只是浅拷贝,如下:
    const person = { 
      name: '令狐冲',
      age: 31,
      '武功': {
        '剑法': '独孤九剑',
        '内功': '易筋经',
        '内功2': '吸星大法'
      }
    }
    
    const p2 = Object.assign({}, person)
    p2['武功']['剑法'] = '辟邪剑法'
    
    console.log(person['武功']['剑法'])  // '辟邪剑法'
    
  • 方法二
    // 先将对象转换为 JSON 对象,在转换为 Object
    const person = { 
      name: '令狐冲',
      age: 31,
      '武功': {
        '剑法': '独孤九剑',
        '内功': '易筋经',
        '内功2': '吸星大法'
      }
    }
    
    const p3 = JSON.parse(JSON.stringify(person))
    

你可能感兴趣的:(14 JavaScript References VS Copying)