如何让JavaScript中所有数组(含新创建数组)的length属性只读?
如何让JavaScript中所有数组的length属性变为只读?
首先得拆解清楚两个核心问题:已存在的数组怎么处理,以及新创建的数组如何默认让length只读,我给你一步步讲明白:
一、为什么你尝试的两种方法无效?
你试过修改Array.prototype.length和Array.length但没效果,原因其实很直观:
- 数组的
length是每个实例的自有属性,并不是从Array.prototype继承来的,所以原型上的修改根本碰不到每个数组自己的length; Array.length是构造函数本身的属性(表示它的参数个数),和数组实例的length完全是两码事,改它自然没用。
二、已存在的数组:只能逐个处理(无全局批量方案)
遗憾的是,JavaScript没有提供遍历所有已存在数组实例的API,所以如果是已经创建好的数组,只能像你最开始那样,逐个用Object.defineProperty设置:
const arr1 = [1,2,3]; const arr2 = ['a','b']; // 逐个设置length为只读、不可配置 Object.defineProperty(arr1, 'length', { writable: false, configurable: false }); Object.defineProperty(arr2, 'length', { writable: false, configurable: false }); arr1.length = 10; // 严格模式下抛出TypeError,非严格模式静默失败
三、新创建的数组:两种可靠方案
如果你想让所有新创建的数组默认拥有只读的length,有两种可行的方式:
方案1:自定义数组子类(推荐,不污染全局)
创建一个继承自Array的子类,在构造函数里自动把实例的length设为只读,既安全又不会影响原生数组的行为:
class ReadOnlyLengthArray extends Array { constructor(...args) { // 先调用父类构造函数创建数组 super(...args); // 把当前实例的length设为只读、不可配置,保持可枚举性和原生数组一致 Object.defineProperty(this, 'length', { writable: false, configurable: false, enumerable: true }); } } // 使用这个子类创建数组 const arr = new ReadOnlyLengthArray(1,2,3); console.log(arr.length); // 3 arr.length = 5; // 严格模式下报错,非严格模式无效果 arr.push(4); // 同样会报错,因为push内部会尝试修改length
方案2:包装原生Array构造函数(不推荐,污染全局)
如果你一定要让所有通过new Array()、Array.of()、Array.from()创建的数组都有只读length,可以包装原生构造函数,但这种方式会污染全局环境,可能和其他代码冲突,谨慎使用:
// 先保存原生的Array构造函数 const OriginalArray = Array; // 重写Array构造函数 Array = function(...args) { const arr = new OriginalArray(...args); Object.defineProperty(arr, 'length', { writable: false }); return arr; }; // 同步处理静态方法Array.of和Array.from Array.of = function(...args) { const arr = OriginalArray.of(...args); Object.defineProperty(arr, 'length', { writable: false }); return arr; }; Array.from = function(iterable, mapFn, thisArg) { const arr = OriginalArray.from(iterable, mapFn, thisArg); Object.defineProperty(arr, 'length', { writable: false }); return arr; }; // 测试 const arr1 = new Array(1,2,3); arr1.length = 10; // 无效果
⚠️ 注意:数组字面量(比如[1,2,3])是由引擎直接创建的,不会经过重写的构造函数,所以这种方法覆盖不到字面量创建的数组。
关键提醒
当把数组的length设为只读后,所有依赖修改length的数组方法(比如push、pop、shift、unshift、splice)都会失效——严格模式下直接抛出错误,非严格模式下静默失败,使用时要注意这一点。
内容的提问来源于stack exchange,提问作者Matus Dubrava
相关产品推荐
相关产品推荐

