为何JavaScript中const无法创建不可变数组?如何实现真正的不可变数组?
理解JavaScript中
const与数组可变性,以及原生实现不可变数组的方法 先给你划个核心重点:const声明的变量只是不能被重新赋值,但这和它指向的数组/对象本身是否可变完全是两码事!
为什么你的两段代码表现天差地别?
第一段:修改数组内容成功的原因
const originalArray = [0, 2, 1, 1, 1]; var newArray = originalArray; var removed = newArray.splice(0,3); console.log(originalArray); // 输出 [ 1, 1 ]
这里const originalArray只是锁定了originalArray这个变量的指向——它永远绑定到最初创建的那个数组对象上。但JavaScript的数组是引用类型,newArray = originalArray只是让newArray也指向同一个数组。而splice是会直接修改原数组的方法,所以操作newArray本质上就是在操作那个共享的数组,originalArray自然也会跟着变。
第二段:重新赋值失败的原因
const originalArray = []; originalArray = [1];
这里你尝试给const声明的originalArray重新赋值一个全新的数组对象,这直接违反了const的核心规则——它不允许变量的指向被更改,所以这段代码会直接抛出语法错误。
原生JavaScript实现真正不可变的数组
不需要第三方库,我们可以用这些原生方案实现数组的不可变:
直接创建不可变数组:
Object.freeze()
这个方法可以冻结一个数组(本质是对象),让它无法被修改、添加或删除元素:const immutableArray = Object.freeze([0, 2, 1, 1, 1]); immutableArray.splice(0, 3); // 抛出错误:Cannot assign to read only property 'length' of object '[object Array]' immutableArray[0] = 5; // 非严格模式下静默失败,严格模式会直接报错注意:
Object.freeze()是浅冻结,如果数组里嵌套了对象或子数组,内部的引用类型还是能被修改的。如果需要深冻结,你可以自己写一个递归函数来处理嵌套结构。操作时返回新数组(避免修改原数组)
日常开发中,优先使用那些不修改原数组、返回新数组的方法,就能实现不可变操作:- 替代
splice:用slice或filterconst originalArray = [0, 2, 1, 1, 1]; // 移除前3个元素,得到新数组 const newArray = originalArray.slice(3); console.log(originalArray); // [0, 2, 1, 1, 1] 原数组完全不变 console.log(newArray); // [1, 1] - 添加元素:用扩展运算符或
concatconst original = [1,2]; const newArr = [...original, 3]; // 得到新数组 [1,2,3] // 也可以用 const newArr = original.concat(3); - 修改元素:用
mapconst original = [1,2,3]; const newArr = original.map(item => item === 2 ? 5 : item); // newArr是[1,5,3],原数组保持原样
- 替代
这样就能在原生JS里实现真正的数组不可变操作啦!
内容的提问来源于stack exchange,提问作者Emeeus
相关产品推荐
相关产品推荐

