JavaScript const关键字

时间:2013-11-16 04:03:41

标签: javascript immutability

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

对于string,它似乎是这样做的:

var x = "asdf";
const constantX = x;

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

输出:

  突变前的

:asdf

     

突变后:asdf

http://jsfiddle.net/hVJ2a/

8 个答案:

答案 0 :(得分:16)

首先你不要改变字符串,你要重新分配引用。

你是对的,const在所有常见浏览器中都不可用。但即使是这样,也是不够的。 const将阻止引用被重新分配 - 但是如果你有一个对可变对象的const引用,那么你还没有完成任何工作。

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

这就是我们提出你的问题,js甚至有不可变的数据结构吗?不,js不随身携带。 Immutable datastructures can be coded as a library - 并且甚至没有定义任务,因此o.foo = 'baz'甚至没有意义。您必须将其写为const var o2 = o.assoc('foo', 'baz'),这将返回一个全新的对象o2,而不是改变o

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

意见如下:

IMO您为生产浏览器应用程序进行实际功能编程的唯一实用选项是等待ClojureScript等成熟的东西。 ClojureScript重新启动了库生态系统,因此在编写库时,它们默认使用不可变数据结构。

你当然可以使用诸如underscore.js和Facebook React之类的工具在javascript中进行半生不熟的函数式编程,这就是我为我构建的生产webapp所做的。但是你必须按惯例建立不变性,人们会在事故中改变事物,或者因为他们不知道更好,你必须应对这些挑战。

答案 1 :(得分:8)

错误。它不是一成不变的,来自MDN:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/const

  

const声明创建对值的只读引用。它   并不意味着它拥有的值是不可变的,只是变量   标识符无法重新分配。

答案 2 :(得分:6)

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

有关详细信息和兼容性,请参阅此MDN article on the const keyword

但是,它不会将引用的数据结构设置为不可变。下面的几个答案使用例如Object.freeze

来解决该问题

答案 3 :(得分:5)

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

const创建不可变变量。是的,“const变量”听起来有争议,但这是我能为JS提出的最接近的术语。

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

如果你想让对象变成不可变的,那么就有Object.freeze(obj)方法。

答案 4 :(得分:4)

您可以使用ES5 Object.defineProperty创建类似CONST的值。糟糕的部分是它必须绑定到一个对象

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

答案 5 :(得分:1)

是的,这是对的。 const只会声明一个只读的命名常量。改变它的价值将无效。

const on MDN的参考:

  

Const创建一个常量,该常量可以是声明它的函数的全局或局部。常量遵循与变量相同的范围规则。

     

常量的值不能通过重新赋值来改变,并且不能重新声明常量。因此,尽管可以在不初始化的情况下声明常量,但这样做是没用的。

     

常量不能与同一范围内的函数或变量共享其名称。

这是browser compatibility matrix

答案 6 :(得分:0)

const是ECMAScript的一个提议功能(与正确的块作用域一起使用它应该替换var和隐式全局)。 ECMAScript Harmony是下一版ECMAScript的一小撮想法。

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

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

你可以这样使用

constants.getX()

答案 7 :(得分:0)

例如:



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."