我有一些原始元素的数组:
const array = [1, 2, 3]
我希望能够暂时冻结此数组的元素并防止对其进行修改。但是,一旦允许修改该元素,就应该有一种解冻该值的方法。
有办法吗?
将这些问题标记为重复的人的题外话:
问题在于冻结数组的元素,而不是冻结整个数组。这不是关于冻结整个阵列的问题的重复。
答案 0 :(得分:4)
您不想冻结值,而是希望冻结保存该值的属性(该数组的"1"
属性您的情况)。您将使用Object.defineProperty
重新定义不带writable
标志的属性。要使其再次可写,请使用writable: true
重新定义它:
const array = [1, 2, 3];
console.log("A", array.join(", ")); // 1, 2, 3
// Freeze it
Object.defineProperty(array, "1", {
value: array[1],
writable: false, // For emphasis (this is the default)
enumerable: true,
configurable: true
});
console.log("B1", array.join(", ")); // 1, 2, 3
array[1] = 42; // <== Doesn't change it
console.log("B2", array.join(", ")); // 1, 2, 3 (still)
// Thaw it
Object.defineProperty(array, "1", {
value: array[1],
writable: true,
enumerable: true,
configurable: true
});
console.log("C1", array.join(", ")); // 1, 2, 3
array[1] = 42; // <== Changes it
console.log("C2", array.join(", ")); // 1, 42, 3 (changed!)
如果执行分配的代码在严格模式下运行,则该分配将是一个例外:
"use strict";
const array = [1, 2, 3];
console.log("A", array.join(", ")); // 1, 2, 3
// Freeze it
Object.defineProperty(array, "1", {
value: array[1],
writable: false, // For emphasis (this is the default)
enumerable: true,
configurable: true
});
console.log("B1", array.join(", ")); // 1, 2, 3
array[1] = 42; // <== Doesn't change it
console.log("B2", array.join(", ")); // 1, 2, 3 (still)
// Thaw it
Object.defineProperty(array, "1", {
value: array[1],
writable: true,
enumerable: true,
configurable: true
});
console.log("C1", array.join(", ")); // 1, 2, 3
array[1] = 42; // <== Changes it
console.log("C2", array.join(", ")); // 1, 42, 3 (changed!)
但是请注意,如果您的代码可以重新定义它以使其可写,那么其他人的代码也可以。
或者,给它一个getter和setter,使其不可配置(因此没有其他人可以重新定义它),并维护一个标志:
const array = [1, 2, 3];
let elementValue = array[1];
let writable = true;
Object.defineProperty(array, "1", {
get: function() {
return elementValue;
},
set: function(newValue) {
if (writable) {
elementValue = newValue;
}
},
enumerable: true,
configurable: false // Again, emphasis
});
console.log("A", array.join(", ")); // 1, 2, 3
array[1] = 42;
console.log("B", array.join(", ")); // 1, 42, 3 -- it changed
writable = false;
array[1] = 67;
console.log("C", array.join(", ")); // 1, 42, 3 -- didn't change
writable = true;
array[1] = 94;
console.log("D", array.join(", ")); // 1, 94, 3 -- changed
自然,您会隐藏其中的一部分,而只暴露数组本身。