在JavaScript中的Const?何时使用它是必要的

时间:2014-01-20 14:56:16

标签: javascript node.js const immutability

我最近遇到了javascript中的const关键字。据我所知,它用于创建immutable variables,我已经测试过以确保它不能重新定义(在node.js中):

const x = 'const';
const x = 'not-const';

// Will give an error: 'constant 'x' has already been defined'

我意识到它还没有在所有浏览器中标准化 - 但我只对node.js / v8的上下文感兴趣,而且我注意到某些developers / projects似乎很重视它var关键字可以用于相同的效果。

问题

何时使用 const 代替 var

每次声明不会重新分配的变量时,是否应该使用它?

如果使用 var 代替 const ,反之亦然,它实际上有什么不同吗?

19 个答案:

答案 0 :(得分:438)

您的问题有两个方面:使用const代替var的技术方面是什么?与此相关的人道相关方面是什么。

技术差异很大。在编译语言中,常量将在编译时被替换,并且它的使用将允许其他优化(如死代码删除)以进一步提高代码的运行时效率。最近(松散使用的术语)JavaScript引擎实际上编译JS代码以获得更好的性能,因此使用const关键字将告知它们上述优化是可能的并且应该完成。这样可以获得更好的性能。

与人类相关的方面是关键字的语义。变量是包含预期会更改的信息的数据结构。常量是包含永不改变的信息的数据结构。如果存在错误的余地,则应始终使用var。但是,并非所有在程序生命周期中永远不会更改的信息都需要使用const声明。如果在不同情况下信息应该更改,请使用var表示即使实际更改未出现在您的代码中也是如此。

答案 1 :(得分:70)

2017年更新

这个答案仍然受到很多关注。值得注意的是,这个答案是在2014年初发布的,自那以后发生了很多变化。 支持现在已成为常态。 All modern browsers现在支持const,因此使用它应该非常安全,没有任何问题。


2014年的原始答案

尽管有fairly decent browser support,我现在还是避免使用它。来自MDN's article on const

  

const的当前实现是特定于Mozilla的扩展,不是ECMAScript 5的一部分。它在Firefox& Chrome(V8)。从Safari 5.1.7和Opera 12.00开始,如果在这些浏览器中使用const定义变量,您仍可以在以后更改其值。它在Internet Explorer 6-10中不受支持,但包含在Internet Explorer 11中.const关键字当前在函数范围内声明了常量(就像用var声明的变量一样)。

然后继续说:

  

const将由ECMAScript 6定义,但具有不同的语义。与使用let语句声明的变量类似,使用const声明的常量将是块作用域。

如果您使用const,则必须添加一种解决方法来支持略微较旧的浏览器。

答案 2 :(得分:37)

为了整合以前的答案,除了性能原因之外,在声明常量变量方面有明显的优势:如果你不小心尝试在代码中更改或重新声明它们,程序将分别不会更改值或抛出错误。

例如,比较:

// Will output 'SECRET'

const x = 'SECRET'
if (x = 'ANOTHER_SECRET') {  // Warning! assigning a value variable in an if condition
    console.log (x)
}

使用:

// Will output 'ANOTHER_SECRET'

var y = 'SECRET'
if (y = 'ANOTHER_SECRET') { 
    console.log (y)
}

// Will throw TypeError: const 'x' has already been declared

const x = "SECRET"

/*  complex code */

var x = 0

// Will reassign y and cause trouble

var y = "SECRET"

/*  complex code */

var y = 0

答案 3 :(得分:29)

const 不可变。

来自MDN

  

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

答案 4 :(得分:28)

为什么要使用const,@ Tibos的答案很棒。

但你说:

  

据我所知,它用于创建不可变变量

错误。变量变量与重新分配不同:

var hello = 'world' // assigning
hello = 'bonjour!' // reassigning

使用const,你不能这样做:

const hello = 'world'
hello = 'bonjour!' // error

但你可以改变你的变量:

const marks = [92, 83]
marks.push(95)
console.log(marks) // [92, 83, 95] -> the variable has been mutated.

因此,使用=符号更改变量值而不使用的任何过程都会静音。

注意:+=例如是......重新分配!

var a = 5
a += 2 // is the same as a = a + 2

因此,最重要的是:const不会阻止您变异变量,它会阻止您重新分配它们。< / p>

答案 5 :(得分:10)

你有很好的答案,但让我们保持简单。

当你有一个已定义的常量时,应该使用

const(读作:在程序执行期间它不会改变)。

例如:

const pi = 3.1415926535

如果您认为以后执行时可能会更改某些内容,请使用var

基于这个例子的实际差异是,const你总是会认为pi是3.14 [...],这是事实。

如果您将其定义为var,则可能是3.14 [...]。

对于更具技术性的答案,@ Tibos在学术上是正确的。

答案 6 :(得分:9)

var :声明一个变量,值初始化为可选。

:声明具有块范围的局部变量。

常量:声明一个只读的命名常量。

例如:

var a;
a = 1;
a = 2;//re-initialize possible
var a = 3;//re-declare
console.log(a);//3

let b;
b = 5;
b = 6;//re-initiliaze possible
// let b = 7; //re-declare not possible
console.log(b);

// const c;
// c = 9;   //initialization and declaration at same place
const c = 9;
// const c = 9;// re-declare and initialization is not possible
console.log(c);//9
// NOTE: Constants can be declared with uppercase or lowercase, but a common
// convention is to use all-uppercase letters.

答案 7 :(得分:6)

根据我的经验,我想使用 const 来设置我可能想要稍后更改的内容而无需寻找已经硬编码的代码的代码,例如文件路径或服务器名称。

你的测试中的错误是另一回事,你要创建一个名为x的另一个变量,这将是一个更准确的测试。

const x = 'const';
x = 'not-const';

答案 8 :(得分:4)

真正的个人偏好。正如你所说,你可以使用const,它不会被重新分配并且是不变的。例如,如果您想分配您的生日。你的生日永远不会改变,所以你可以把它当作常数。但是你的年龄确实发生了变化,这可能是一个变数。

答案 9 :(得分:3)

摘要:

const创建不可变绑定意味着const变量标识符不可重新分配。

const a = "value1";

你不能用

重新分配它
a = "value2";

但是,如果const标识符包含一个对象或一个数组,只要我们不重新赋值它就可以改变它的值。

const x = { a: 1 }

x.a = 2; //is possible and allowed

const numbers = [1, 2];
numbers.push(3); //is possible and allowed

请注意 const 块范围,就像一样,与 var 不同(这是功能范围的)

简而言之,当某些内容不太可能通过重新分配进行更改时,请使用 const ,否则请使用 var 取决于您希望拥有的范围。

当代码明显死亡时,通过重新分配可以改变什么,以及什么不可以改变代码,这更容易理解代码。将const更改为let非常简单。默认情况下使用const会让你在这样做之前三思而后行。在许多情况下,这是一件好事。

答案 10 :(得分:2)

它提供: 1)常量引用,例如const x = [] - 可以修改数组,但x不能指向另一个数组;和 2)阻止范围界定。 const和let将在ecma6 / 2015中一起替换var 请参阅https://strongloop.com/strongblog/es6-variable-declarations/

上的讨论

答案 11 :(得分:2)

Main point is that how to decide which one identifier should be used during development.
In java-script here are three identifiers.

1. var (Can re-declared & re-initialize)
2. const (Can't re-declared & re-initialize, can update array values by using push)
3. let (Can re-initialize but can't re-declare)
  

'var':在编码时,当我们谈论代码标准时,我们通常使用标识符的名称,该标识符易于被其他用户/开发人员理解。   例如,如果我们正在考虑使用许多函数,这些函数将使用一些输入并对其进行处理并返回一些结果,例如:

**Example of variable use**

function firstFunction(input1,input2)
{
 var process = input1 + 2; 
 var result = process - input2;
 return result;
}


function otherFunction(input1,input2)
{
 var process = input1 + 8; 
 var result = process * input2;
 return result;
}
  

在以上示例中,两个函数均产生不同的2结果,但使用相同的变量名称。在这里,我们可以看到'process'和'result'都被用作变量,应该使用。

 **Example of constant with variable**

 const tax = 10; 
 const pi = 3.1415926535; 

function firstFunction(input1,input2)
{
 var process = input1 + 2; 
 var result = process - input2;
 result = (result * tax)/100; 
 return result;
}


function otherFunction(input1,input2)
{
 var process = input1 + 8; 
 var result = process * input2 * pi;
 return result;
}
  

在Java脚本中使用“ let”之前,我们必须在js文件顶部添加“ use strict”

 **Example of let with constant & variable**

 const tax = 10; 
 const pi = 3.1415926535; 
 let trackExecution = '';

function firstFunction(input1,input2)
{
 trackExecution += 'On firstFunction'; 
 var process = input1 + 2; 
 var result = process - input2;
 result = (result * tax)/100; 
 return result;
}


function otherFunction(input1,input2)
{
 trackExecution += 'On otherFunction'; # can add current time 
 var process = input1 + 8; 
 var result = process * input2 * pi;
 return result;
}

 firstFunction();
 otherFunction();
 console.log(trackExecution);
  

在上面的示例中,您可以跟踪在特定操作期间什么时候不使用哪个功能。

答案 12 :(得分:1)

首先,关于const的三个有用的事情(除了与let共享的范围改进之外):

  • 它为以后阅读代码的人员提供文件,证明该值不得更改。
  • 它会阻止您(或任何跟随您的人)更改该值,除非他们返回并故意更改声明。
  • 可能 在优化方面为JavaScript引擎保存一些分析。例如,您已声明该值无法更改,因此引擎不必进行工作以确定该值是否发生变化,以便根据不更改的值来决定是否进行优化。

您的问题:

  

何时使用const代替var

可以在您声明其值永远不会更改的变量时执行此操作。您是否认为合适完全取决于您的偏好/您的团队的偏好。

  

每次声明不会重新分配的变量时是否应该使用它?

这取决于你/你的团队。

  

如果var is used in place of const`或反之亦然,它实际上有什么不同吗?

是:

  • varconst有不同的范围规则。 (您可能希望与let而不是var进行比较。)具体来说:constlet是块范围的,在全球范围内使用时,请&#39 ; t在全局对象上创建属性(即使它们确实创建了全局对象)。 var具有全局范围(在全局范围内使用时)或函数范围(即使在块中使用),并且在全局范围内使用时,在全局对象上创建属性。
  • 查看我的&#34;三个有用的东西&#34;以上,他们都适用于这个问题。

答案 13 :(得分:1)

varlet的语义

varlet是对机器和其他程序员的声明:

我打算在执行过程中更改此赋值。不要依赖此分配的最终值。

使用varlet的含义

varlet迫使其他程序员读取从声明到最终使用的所有中间代码,并在程序执行的那一刻说明赋值的原因。

它们削弱了ESLint和其他语言服务的机器推理能力,从而可以在以后的分配中正确检测错误键入的变量名,并在内部作用域忘记声明的情况下重新使用外部作用域变量名的作用域。

它们还使运行时在所有代码路径上运行许多迭代,以在优化它们之前检测到它们实际上是常量。尽管这比错误检测和开发人员易理解性要小。

何时使用const

如果引用的值在执行过程中没有改变,则表示程序员意图的正确语法为const。对于对象,更改引用的值意味着指向另一个对象,因为引用是不可变的,但是对象不是。

const”对象

对于对象引用,不能将指针更改为另一个对象,但是创建并分配给const声明 的对象是可变的。您可以在const引用的数组中添加或删除项目,并在const引用的对象上更改属性键。

要实现不可变的对象(这又使您的代码更易于为人类和机器推理),可以在声明/分配/创建处Object.freeze进行对象操作,如下所示:

const Options = Object.freeze(['YES', 'NO'])

Object.freeze确实会影响性能,但是由于其他原因,您的代码可能很慢。您要对其进行配置。

您还可以将可变对象封装在状态机中,并将深层副本作为值返回(这是Redux和React状态的工作方式)。请参见Avoiding mutable global state in Browser JS,以获取有关如何根据第一条原则进行构建的示例。

varlet非常合适时

letvar表示可变状态。在我看来,它们应该仅用于建模实际可变状态。诸如“ 连接是否还存在?”之类的东西。

最好将它们封装在可测试的状态机中,这些状态机公开表示“ 连接的当前状态”的常量值,该常量在任何时间点都是常量,而其余的代码是什么实际上是感兴趣的。

通过编写副作用和转换数据已经足够困难。通过创建带有变量的可变状态,将每个功能变成不可测试的状态机,只会增加复杂性。

有关更细微的解释,请参见Shun the Mutant - The case for const

答案 14 :(得分:0)

&#39; const的&#39;表示您的代码不会重新分配标识符。这是一篇很好的文章,关于何时使用&#39; const&#39;&#39; let&#39;或者&#39; var&#39; https://medium.com/javascript-scene/javascript-es6-var-let-or-const-ba58b8dcde75#.ukgxpfhao

答案 15 :(得分:0)

我不是JS编译业务的专家,但有理由说,v8使用const标志

通常在声明和更改一堆变量之后,内存会碎片化,v8停止执行,暂停几秒钟,进行gc或垃圾回收。

如果使用const v8声明变量,则可以确信将其置于其他const变量之间的紧凑固定大小容器中,因为它永远不会更改。 它还可以保存该数据类型的正确操作,因为类型不会更改。

答案 16 :(得分:0)

阅读以下文章,它很好地解释了。 let vs var vs const

答案 17 :(得分:0)

let const (均在块范围内)之间做出决定时,请始终首选 const ,以便在编码。这样,如果您尝试重新声明该变量,则会收到错误消息。如果没有其他选择,只能重新声明,只需切换为 let 。请注意,正如Anthony所说, const 值不是不可变的(例如, const 对象可以使属性发生突变)。

关于 var ,由于ES6已发布,所以我从未在生产代码中使用过它,也没有想到用例。可能考虑使用它的一点是JavaScript hosting-在不提升 let const 的同时,声明 var 。但是,请注意,用 var 声明的变量具有函数作用域,而不是块作用域(«如果在任何函数外部声明,它们将在整个程序中全局可用;如果在函数内部声明,则仅可在函数本身»中找到,位于HackerRank-变量声明关键字中)。您可以将 let 视为 var 的块范围版本。

答案 18 :(得分:0)

我的意见:

问:问。什么时候使用const代替var
答:永远不会!

问:是否应在每次声明一个不会被重新分配的变量时使用它?
答:永远不会!这样会减少资源消耗...

问:问。如果使用var代替const,实际上有什么区别?反之亦然?
A:是的!使用var是可行的方法!开发工具更加轻松,并且无需创建新文件进行测试即可保存。 ({var不能代替const-const试图取代var的位置...)

附加A:let也是如此。 JavaScript是一种松散的语言-为什么const将其归类?!!