const定义的数组内容可变但指针不能变

一个const与数组扩展运算符、push、splice的悲伤故事。const定义的数组内容可变但指针不能变,push改变内容但没改变指向

问题描述

  • 打算往const定义的数组gridColumns里添加另一个数组paymentColumns,结果报错:Error: "gridColumns" is read-only,但是换成push/splice又不报错了,当时想不通为啥 只读数组 不能 扩展运算符 却 可以push/splice,毕竟push/splice不也改变了原数组吗
1
2
3
4
5
6
7
8
9
10
11
12
// 注意:问题就在这,是const定义的,内容可变但指针不能变!!只读数组就是这么来的
const gridColumns = this.init().formatRole(columns)

// 没问题,正常
gridColumns.push(...paymentColumns)

// 使用下面这种写法会报错Error: "gridColumns" is read-only
// 因为gridColumns是const定义的,这样相当于重新赋值,是会改变指针指向的,而push和splice是修改数组内容,不改变指针指向,所以不会报错
gridColumns = [
...gridColumns,
...paymentColumns
]

原因

  • gridColumns是const定义的,内容可变但指针不能变!!只读数组就是这么来的
  • push/splice之所以可以操作 只读数组gridColumns 是因为push/splice只是修改内容,并未改变指针指向
  • 扩展运算符之所以不行,是因为不仅扩开来还重新赋值了,重新赋值是会改变指针指向的,const又不允许改变指针指向,就报错了

扩展

  • 突然想到以前的一个问题,关于const定义的引用类型是否可以重新定义
  • 重点:const定义的只读含义是“内容可变但指针不能变”
  • 答案:值类型不可以,毕竟指针会直接改;但引用类型只有重新赋值时才会修改指针指向,所以修改内容不改指针指向是可以的
  • 例子:
    • const定义一元数组,一元数组不能重新定义,但数组元素可改,一元数组也可新增数组元素
    • const定义对象,对象不能重新定义,但对象属性值可以,也可以给对象添加新属性
    • const定义二元数组,二元数组不能重新定义。数组元素为对象时,数组元素可变,数组元素内属性值可变,也可给数组元素新增属性;数组元素为数组时,数组元素可变,数组元素内值也可变
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      const a = [11, 22]
      a = [33] // 报错
      a[0] = 33 // a = [33, 22]
      a[2] = [11] // a = [33, 22, [11]]

      const b = { a:1, c:2 }
      b = { e: 4 } // 报错
      b.a = 33 // b = { a:33, c:2 }
      b.f = 44 // b = { a:33, c:2, f: 44 }

      const r = [{ a: 1 }]
      r = [{ b: 2 }] // 报错
      r[0] = { b: 2 } // 报错
      r[0].a = 33 // r = [{ a: 33 }]
      r[0].v = 44 // r = [{ a: 33, v: 44 }]

      const t = [[1, 2]]
      t = [[22]] // 报错
      t[0]=[4, 5] // t = [[4, 5]]
,