关于immutability:JavaScript const关键字

JavaScript const Keyword

javascript中的const关键字是否创建了对不可变数据结构的不可变引用?[我假设javascript中存在不可变的数据结构。]

对于string来说,似乎是这样:

1
2
3
4
5
6
var x ="asdf";
const constantX = x;

alert("before mutation:" + constantX);
x ="mutated"
alert("after mutation:" + constantX);

输出:

before mutation: asdf

after mutation: asdf

http://jsfiddle.net/hvj2a/


首先,您没有改变字符串,而是重新分配引用。

你说得对,const并不是所有常见的浏览器都可以使用的。但即使是这样,也不够。const将阻止重新分配引用,但如果您对可变对象有常量引用,则不会完成太多工作。

1
2
3
const var o = { foo: 'bar' };
o = { foo: 'baz'}; // throws
o.foo = 'baz'; // allowed

所以我们来问一下,JS是否有不变的数据结构?不,JS不带。不可变的数据结构可以被编码为一个库——甚至没有定义赋值,所以o.foo = 'baz'甚至没有意义。你必须把它写成const var o2 = o.assoc('foo', 'baz'),它将返回一个全新的对象o2,而不是突变o

但是,如果没有人使用不可变的数据结构,作为一个库并不意味着什么。例如,如果Angular使用常规的JavaScript数据结构,那么也必须使用它们。否则,您必须在代码和角度之间的边界处在可变和不可变之间进行转换。

意见如下:

在我看来,为生产浏览器应用程序进行真正的功能性编程的唯一可行的选择就是等待Clojurescript之类的东西成熟。ClojureScript重新启动库生态系统,以便在编写库时,它们默认使用不可变的数据结构。

当然,您可以使用诸如underline.js和facebook react之类的工具在javascript中进行半成品函数编程,这正是我为自己构建的生产webapps所做的。但是你必须通过惯例来确定不可变性,人们会在偶然中改变事物,或者因为他们不知道任何更好的东西,你必须应对这些挑战。


错了。它不是不可变的,从MDN:

https://developer.mozilla.org/en-us/docs/web/javascript/reference/statements/const

The const declaration creates a read-only reference to a value. It
does not mean the value it holds is immutable, just that the variable
identifier cannot be reassigned.


是的,它确实创建了一个不可变的引用,但它并没有被标准化,并且在所有浏览器中都不受支持。

有关详细信息和兼容性,请参阅有关const关键字的MDN文章。

但是,将引用的数据结构设置为不可变并没有任何作用。下面的几个答案解决了这个问题,例如,使用EDOCX1[1]


唯一不变的数据结构(在堆上分配的)是字符串。默认情况下,所有其他类似对象(如对象、数组和函数)都是可变的。

const创建不可变变量。是的,"常量变量"听起来有争议,但这是我能想到的最接近JS的术语。

不能在声明之外更改常量内容。但它可能包含对对象的引用,例如,对象本身是可变的。所以您可以通过对它的常量引用来修改它的属性。

如果你想使对象不可变,那么有一个object.freeze(obj)方法。


可以使用es5 object.defineproperty创建类常量的值。最糟糕的部分是它必须绑定到一个对象上

1
2
3
4
5
6
7
CONSTS = {};
Object.defineProperty(CONSTS, 'FOO', {
    value: 'bar'
});

CONSTS.FOO = 'derp' // Will throw error in strict mode
delete CONSTS.FOO // will throw error in strict mode

是的,没错。常量只声明一个只读的命名常量。更改其值将没有效果。

MDN上常量的参考:

Const creates a constant that can be global or local to the function in which it is declared. Constants follow the same scope rules as variables.

The value of a constant cannot change through re-assignment, and a constant cannot be re-declared. Because of this, although it is possible to declare a constant without initializing it, it would be useless to do so.

A constant cannot share its name with a function or a variable in the same scope.

这是浏览器兼容性矩阵。


例如:

1
2
3
4
5
6
7
8
const basket = [1,2,3];

//Even though the variable is declared as const this one works
basket[0] = 1111;
console.log(basket);

//This one throws an error
basket ="Other primitive type."


const是ecmascript的一个被提议的特性(加上一个适当的块范围的let,它应该替换var和隐式全局)。EcmaScript Harmony是下一个版本EcmaScript的一个想法袋。

如果您要查找只读变量,可以这样做

1
2
3
4
var constants = new (function() {
  var x = 200;
  this.getX = function() { return x; };
 })();

你可以这样用

1
constants.getX()