【问题标题】:JavaScript const KeywordJavaScript 常量关键字
【发布时间】:2013-11-29 15:20:24
【问题描述】:

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/

【问题讨论】:

  • 看来您正在更改x,而不是constantX,但显然它确实保持不变。
  • 它不是一成不变的,请看下面我的回答。
  • 这个JavaScript const 视频可能会有所帮助!

标签: javascript immutability


【解决方案1】:

错了。它不是一成不变的,来自MDN Documentation for const

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

【讨论】:

  • 嗯,是的,它创建了对可变数据的引用,但根据定义,引用本身是不可变的。因此,这个问题的答案是“它创建了对可变数据结构的不可变引用”。
【解决方案2】:

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

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

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

来解决该问题

【讨论】:

  • 知道为什么它不被全部支持吗?
  • 因为它是新的。 MDN 文章说:const is going to be defined by ECMAScript 6.
  • 它不是一成不变的,请看下面我的回答。
【解决方案3】:

例如:

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

【讨论】:

    【解决方案4】:

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

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

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

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

    【讨论】:

    【解决方案5】:

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

    您说得对,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 中进行半生不熟的函数式编程,这就是我为我构建的生产 webapps 所做的。但是你必须按照惯例建立不变性,人们会在意外或因为他们不知道更好的情况下改变事物,你必须应对这些挑战。

    【讨论】:

      【解决方案6】:

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

      【讨论】:

        【解决方案7】:

        const 是 ECMAScript 的一个提议特性(连同适当的块作用域让它应该替换 var 和隐式全局)。 ECMAScript Harmony 是 ECMAScript 下一版本的灵感来源。

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

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

        你可以这样使用

        constants.getX()
        

        【讨论】:

          【解决方案8】:

          是的,没错。一个 const 只会声明一个只读的命名常量。更改它的值不会有任何效果。

          const on MDN的参考:

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

          常量的值不能通过重新赋值来改变,常量不能重新声明。因此,虽然可以不初始化就声明一个常量,但这样做是没有用的。

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

          这是browser compatibility matrix

          【讨论】:

            猜你喜欢
            • 2011-12-30
            • 2012-12-18
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-05-27
            相关资源
            最近更新 更多