如何使Javascript变量完全不可变?

3

我听到过类似的问题,但没有得到我想要的答案; 我不认为const是因为: 1)它并没有使它真正成为不可变的,它只是使引用成为不可变的 2)它会影响作用域,而我希望它在块外也能工作 3)并非所有浏览器都支持它

 {
     const hello = ["hello", "world"];
     hello.push("!!!");
     console.log(hello);//outputs "hello", "world", "!!!"
 }
 //and it doesn't, and shouldn't, work here
     console.log(hello);

3
const hello = Object.freeze(["hello", "world"]); - Pointy
2
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/freeze - connexo
3个回答

4

只需要使用 Object.freeze 方法即可。

const immutableArray = Object.freeze([1,2,4])

谢谢,但那只适用于对象!它怎么能适用于任何数据类型呢? - Sapphire_Brick
const name = Object.freeze(<anything>) 运行良好。 <anything> 可以是数组、对象、数字、字符串、布尔值或其他任何类型。在您的浏览器中尝试一下。 - Intervalia
是的。抱歉我错过了你的评论。但是,Object.freeze 接受任何引用类型。请记住,在 js 中几乎所有东西都是对象(除了原始类型)。 - Dupocas
@Dupocas 数组、字符串、布尔值、数字等不都是原始类型吗?尽管如此,它确实可以在任何东西上工作,但现在我想想这样做是毫无意义的:例如 Object.seal(4) - Sapphire_Brick

2
你可以使用 Object.freeze 来实现这一点(显然只能用于object)。最初的回答。

const hello = Object.freeze(["hello", "world"]);

// hello.push("!!!");
// will throw "TypeError: can't define array index property past the end of an array with non-writable length"

// hello.length = 0;
// will fail silently

// hello.reverse();
// will throw "TypeError: 0 is read-only"

// hello[0] = "peter";
// will fail silently

来自MDN:

Object.freeze() 方法可以冻结一个 object。被冻结的对象将无法再被更改,冻结一个对象会防止新属性被添加到它上面,已有属性被删除,防止更改已有属性的可枚举性、可配置性或可写性,并防止现有属性的值被更改。此外,冻结一个对象还会防止其原型被更改。freeze() 返回与传入的相同的对象。

然而,没有关键字可以定义完全不可变的变量,除非在变量的值上使用 Object.freezeObject.seal

对于一种较少限制的方法,Javascript 还具有 Object.seal()


1
不使用const的方法是使用Object.defineProperty,就像我想要的那样,在作用域方面它的行为类似于var:
{
    Object.defineProperty(typeof global === "object" ? global : window, "PI", {
        value:        Object.seal(3.141593),
        enumerable:   true,
        writable:     false,
        configurable: false
    });
}
console.log(PI); // 3.141593

唯一的问题在于,它在严格模式之外不会抛出错误。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接