在Javascript中,是否可以创建一个长度保持不变的数组?
例如,创建一个长度为2的数组A。随后,任何试图调用A.push()或A.pop(),或设置A [5]的值都将失败。A.length将始终为2。
这就是类型化数组(例如Float32Array)已经实现的方式。它们具有固定的大小。但我想知道在常规数组上获得相同行为的方法。
对于我的特定情况,我想创建一个固定长度的数组,其中每个条目都是一个对象。但我仍然想了解一般问题的答案。
在Javascript中,是否可以创建一个长度保持不变的数组?
例如,创建一个长度为2的数组A。随后,任何试图调用A.push()或A.pop(),或设置A [5]的值都将失败。A.length将始终为2。
这就是类型化数组(例如Float32Array)已经实现的方式。它们具有固定的大小。但我想知道在常规数组上获得相同行为的方法。
对于我的特定情况,我想创建一个固定长度的数组,其中每个条目都是一个对象。但我仍然想了解一般问题的答案。
new Array(5)
创建一个固定大小的空值数组,并保持它们的大小不变。const fixedQueue = new Array(5)
fixedQueue.push = function (i) {
this.shift();
return Array.prototype.push.call(this, i)
}
fixedQueue.unshift = function (i) {
this.pop()
return Array.prototype.unshift.call(this, i)
}
目前的答案是肯定的,你可以这样做。有几种方法可以实现,但一些网络浏览器有自己的“解释”。
var x = new Array(10).fill(0);
// Output: undefined
Object.freeze(x);
// Output: Array [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
x.push(11)
// Output: TypeError: can't define array index property past the end of an array with non-writable length
x.pop()
// Output: TypeError: property 9 is non-configurable and can't be deleted [Learn More]
x[0]=10
// Output: 10 // You don't throw an error but you don't modify the array
x
// Output: Array [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ]
需要注意的是,如果数组是对象,则需要进行深度冻结。深度冻结的代码在这里。
包装数组的类(如果不想抛出异常,这是更好的选择)
使用ES2015代码应该可以解决以下问题,但实际上并没有:
var x = new Array(10).fill(0);
Object.freeze( x.length );
x.push(3);
console.log(x);
x.length
是一个数字,Object.freeze(x.length);
除了返回 x.length
之外什么也不会做。 - tim-we当使用 shift 和 push 时,在固定长度的数组中必须有前后长度控制,才能选择从数组开头或结尾删除项目,然后添加或拒绝新项目。这是我最快的解决方案。 如果只使用键来访问数组,可以轻松控制并期望固定大小的行为。对象和数组都可以使用。
是的,此函数用于创建定长数组,使其不仅是单个数组,而且是动态的。您可以创建不同的有限数组,只需创建一个新变量并将其值设置为createLimtedArray(array_limit)
的返回值即可。请注意,我的解决方案使用推送方法,因此在核心中创建的数组无需调用任何额外的功能即可进行推送。如果要创建多个不同长度的枚举数组,则非常好用。
// this call back check the length and return true or false if length > limit
const theCallback = (theArray, limit)=>{
const check = theArray.length <= limit;
return theArray.length;
}
const createLimtedArray = (arrayLength)=>{
const limtedArray = [];
addPushEventListener(limtedArray, theCallback, arrayLength);
return limtedArray;
}
function addPushEventListener(theArray, theCallback, limit){
// change the push method
theArray.push = (e)=> {
// call the normal push method and give it the item
// apply something callback on array before push
//if (theArray.length <= limit){return false;}
Array.prototype.push.call(theArray, e);
const arrLength = theCallback(theArray, e, limit);
const acceptPush = (arrLength <= limit);
const s = limit == 1 ? '' : 's';
if (!acceptPush){
console.log("sorry array only accept " + limit + " item" + s);
theArray.pop();
}
// apply push or
};
}
// first limited array
let x = createLimtedArray(1);
console.log("---------------Array X----------------");
x.push("New X Item 1");
x.push("New X Item 2");
console.log(x);
console.log("");
let y = createLimtedArray(3);
y.push("New Y Item 1");
y.push("New Y Item 2");
y.push("New Y Item 3");
y.push("New Y Item 4");
console.log(y);
console.log("--------------------------------------");
console.log("");
我知道这是一个老问题,但现在有一个叫做fixed-array的节点模块可以做到这一点。
push
、pop
或其他修改方法。如果希望保留内部封装的数组不可访问,可以使用闭包。 - salezicaobject
,然后freeze
它,这样属性就无法被修改。请注意,如果您有一个对象的对象,则冻结仅适用于您冻结的对象,而不适用于任何嵌套对象。 - Andy