为啥push改变了数组,却不能用let来定义

无涯
  • 103

let arr = [1,2,3,4];
arr.push(5);
console.log(arr); // [1,2,3,4,5];

arr改变了,为啥eslint却说arr没有改变,建议用const

回复
阅读 737
6 个回答
✓ 已被采纳

说简单是个简单问题,但是深究起来其实蛮奇怪的

const一般来说是声明常量,如果没记错kotlin中const真的就是引用不可变,以及引用的引用不可变,真正的常量。很不巧,JavaScript中对于const只要求了引用不可变。

const a = [1,2]

可以描述为常量a指向一个数组,这个指向不可变。粗暴的理解数组就是个容器,容器内部想怎么便就怎么变,反正指向没有变。

const 只是意味着变量不能被重新分配,而不是你不能操纵它.

const a = []
a = [1] // x 错误

const在引用类型和基本类型不同

  1. 基本类型:不能重新赋值
  2. 引用类型比如这里的Array,实际js中const限定的是地址不变,地址指向的值可以变化,表现出来的就是

    1. 不能重新赋值,arr=另外一个随便什么,会报错uncaught TypeError: Assignment to constant variable.
    2. 可以改变引用类型里面的值,比如你说的push

eslint建议用const

eslint自己加戏了,可以把这条规则关掉,使用let定义

    'prefer-const': 'off',

前端const泛滥

  1. 网上有提到用const的好处
  2. 从接触代码起一直const是常量,全大写+下划线,所以我关了这个规则,只有常量和不变的配置信息使用const

[1,2,3,4] 是一个数组,它由变量 arr 引用(也就是通过这个变量能拿到这个数组)。

如果 arr.push(5) 改变的是数组,它内部添加了一个元素 5

如果 arr = [1,23],改变的是变量,arr 现在引用了另一个数组(但原来那个数组还在,只是没有被变量引用,稍后会被垃圾回收)

const arr = ... 这里的 const 是修饰的 arr,也就是说,这样修饰之后 arr = ... 就不行了,不能让 arr 去引用别的东西。

但数组本身还是不受约束,仍然可以进行 push() 等操作改变自身内部数据。

const声明创建一个值的只读引用。但这并不意味着它所持有的值是不可变的,只是变量标识符不能重新分配。

JS、TS里的const代表的是引用不可变,也就是定义的变量不可重新赋值,或者说,这个变量右侧只能实行一次=操作:

const x = [1, 2, 3, 4];
x = [5, 6, 7]; // Cannot assign to 'x' because it is a constant

x.push()、修改对象的属性x.length并不会修改变量的引用,是合法的操作:

const x = [1, 2, 3, 4];
x.push(5); // ok
x.length = 0; //ok

如果你要想实现类似其他语言那样,属性也不可变的话,应该使用Object.freeze,这样在严格模式下就会报错。

'use strict';
const list = Object.freeze([1, 2, 3, 4]);
list.push(5); // Cannot add property 4, object is not extensible
'use strict';
const o = Object.freeze({ a: 1 });
o.b = 2; // Cannot add property b, object is not extensible
宣传栏