JavaScript const 关键字

8
在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/


2
看起来你正在改变 x,而不是 constantX,但是显然它仍然保持不变。 - Havenard
它不是不可变的,见下面我的答案。 - Anthony
这个JavaScript const视频可能会有所帮助! - Mahmoud
8个回答

17

首先,你并没有改变字符串本身,而是重新分配了引用。

你说的没错,const 在某些常见的浏览器中不可用。但即使它可用,也是不够的。如果你有一个指向可变对象的 const 引用,const 只能防止重新分配引用,对于实现功能来说帮助不是很大。

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

那么这就引出了你的问题,JavaScript是否具有不可变数据结构?不是的,JavaScript本身并没有提供这种功能。不可变数据结构可以通过库来实现 - 而且赋值语句甚至没有被定义,因此o.foo='baz'甚至没有意义。你必须把它写成const var o2 = o.assoc('foo', 'baz'),它将返回一个全新的对象o2,而不是改变o

但是,如果没有人使用作为库的不可变数据结构,那么这种库就没有多大用处。例如,如果Angular使用常规JavaScript数据结构,则您也必须使用它们。否则,在您的代码和Angular之间的边界上,您必须在可变和不可变之间进行转换。

下面是个人观点:

在生产浏览器应用程序中进行真正的函数式编程的唯一实用选择是等待类似ClojureScript这样的东西成熟。ClojureScript重新启动了库生态系统,因此随着库的编写,它们默认使用不可变数据结构。

当然,你可以使用像underscore.js和Facebook React这样的工具在JavaScript中进行不完全的函数式编程,这就是我为构建生产Web应用程序所做的事情。但你必须通过约定来确立不可变性,而且人们会在意外情况下或因为不知道更好的方法而改变东西,你必须处理这些挑战。


8

错误。从MDN const文档中可以看出,它不是不可变的:

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


1
好的,是的,它创建了对可变数据的引用,但根据定义,引用本身是不可变的。因此,对于这个问题的答案将是:“它创建了对可变数据结构的不可变引用”。 - Agamemnus

7

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

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

然而,它并没有对所引用的数据结构设置为不可变。下面的几个答案使用Object.freeze等方法来回答这个问题。


1
任何想法为什么它不支持所有平台? - Kevin Meredith
1
因为它是新的。MDN文章说:“const将由ECMAScript 6定义”。 - Robbie Wxyz
1
它不是不可变的,见下面我的答案。 - Anthony

7
唯一的不可变数据结构(分配在堆上的)是字符串。所有其他对象,如对象、数组和函数,默认情况下都是可变的。 const 创建一个不可变的变量。是的,“const 变量”听起来有争议,但这是我能想到的最接近 JS 的术语。
const 内容在声明之外无法更改。但它可能包含引用,例如指向本身可变的对象。因此,您可以通过 const 引用修改其属性。
如果您想使对象不可变,则有一个 Object.freeze(obj) 方法。

谢谢。我已经研究了这个 jsfiddle(http://jsfiddle.net/hVJ2a/4/)以理解您的观点。 - Kevin Meredith

5
你可以使用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

1

没错。const 只声明一个只读的命名常量。改变它的值将没有任何效果。

MDN 上 const 的参考资料:

const 创建一个可以是全局或局部于函数中声明的常量。常量遵循与变量相同的作用域规则。

常量的值不能通过重新赋值而更改,并且常量不能被重新声明。因此,尽管可以声明一个未初始化的常量,但这样做是无用的。

常量不能与同一作用域中的函数或变量共享名称。

这里是浏览器兼容性矩阵


0

const是ECMAScript的一个拟议特性(与适当的块级作用域let一起,它应该替换var和隐式全局)。ECMAScript Harmony是下一个版本ECMAScript的一堆想法。

如果你正在寻找只读变量,可以像这样做

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

你可以像这样使用

constants.getX()

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


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