50

我想知道ES6letconstin之间有什么区别。它们都是块作用域,如以下代码中的示例:

const PI = 3.14;
console.log(PI);

PI = 3;
console.log(PI);

const PI = 4;
console.log(PI);

var PI = 5;
console.log(PI);

在 ES5 中,输出将是:

3.14
3.14
3.14
3.14

但在 ES6 中它将是:

3.14
3
4
5

我想知道为什么ES6允许改变const值,问题是为什么我们现在应该使用 'const' ?我们可以改用“让”吗?

注意jsbin可用于测试,选择JavaScript运行ES5代码,Traceur运行ES6能力。

4

10 回答 10

64

let和之间的区别在于const,一旦使用 将值/对象绑定到变​​量const,就不能重新分配给该变量。换句话说示例:

const something = {};
something = 10; // Error.

let somethingElse = {};
somethingElse = 1000; // This is fine.

问题细节声称这是对 ES5 的更改——这实际上是一种误解。在只支持 ECMAScript 5 的浏览器中使用const总是会抛出错误。该const声明在 ECMAScript 5 中不存在。其中的行为要么是 JS Bin 误导了正在运行的 JavaScript 类型,要么是浏览器错误。

在实践中,浏览器并不是一次性从 0% 支持 ECMAScript 2015 (ECMAScript 6) 到 100% — 功能是逐位添加的,直到浏览器完全兼容。JS Bin 所说的“JavaScript”只是指您的浏览器当前支持的任何 ECMAScript 功能——它并不意味着“ES5”或“ES6”或其他任何东西。许多浏览器都支持const并且let在它们完全支持 ES6 之前,但有些(如 Firefox)被处理constlet一段时间。提问者的浏览器可能支持let但未const正确实现它们。

其次,像 Babel 和 Traceur 之类的工具不会让 ES6 在旧版浏览器中“运行”——而是将 ES6 代码转换为 ES5 做大致相同的事情。Traceur 可能会将const语句转换为var语句,但我怀疑它总是强制const语句的语义在 ES5 中完全复制。使用 JS Bin 使用 Traceur 运行 ES6 不会得到与在完全符合 ES6 规范的浏览器中运行 ES6 完全相同的结果。


重要的是要注意,const不会使值或对象不可变。

const myArray = [];
myArray.push(1); // Works fine.
myArray[1] = 2; // Also works fine.
console.log(myArray); // [1, 2]
myArray = [1, 2, 3] // This will throw.

目前使对象(浅)不可变的最佳方法可能是使用Object.freeze()它。但是,这只会使对象本身成为只读的;对象属性的值仍然可以改变。

于 2015-08-09T03:49:15.847 回答
26

您所看到的只是一个实施错误。根据ES6 规范 wikiconstconst是:

一次初始化,此后只读绑定形式很有用,并且在现有实现中具有先例,以 const 声明的形式。

它是只读的,就像现在一样。constTraceur 和 Continuum 中的 ES6 实现有问题(他们可能只是忽略了它)

这是关于 Traceur 未实施的 Github 问题const

于 2014-03-10T18:49:37.770 回答
9

  • 在编程中使用块作用域。
  • 对于每个块,让我们创建自己的新范围,您无法在该块之外访问。
  • 值可以根据需要更改多次。
  • let 对于绝大多数代码都非常有用。它可以大大提高您的代码可读性并减少编程错误的机会。

    let abc = 0;
    
    if(true)
     abc = 5 //fine
    
    if(true){
      let def = 5
    }
    console.log(def)
    

常量

  • 它允许您对变量保持不变。
  • const 在可读性和可维护性方面都是一个很好的做法,并且避免使用魔法文字,例如

    // Low readability
    if (x > 10) {
    }
    
    //Better!
    const maxRows = 10;
    if (x > maxRows) {
     }
    
  • 必须初始化 const 声明

     const foo; // ERROR: const declarations must be initialized
    
  • 一个 const 是块作用域,就像我们在 let:+ 中看到的那样
const foo = 123;
if (true) {
    const foo = 456; // Allowed as its a new variable limited to this `if` block
}
于 2017-05-16T06:58:16.000 回答
5

概括:

let和关键字都是const声明块作用域变量的方法。但是有一个很大的区别:

  • 声明的变量let可以重新赋值。
  • 声明的变量const必须在声明时初始化并且不能重新分配。

如果您尝试重新分配使用const关键字声明的变量,您将收到以下错误(chrome devtools):

const 重新分配错误

我们为什么要使用这个?

如果我们知道要分配一次变量并且不想重新分配变量,则使用const关键字具有以下优点:

  • 我们在代码中传达我们不想重新分配变量。这样,如果其他程序员查看您的代码(甚至是您自己的代码,您之前编写的代码),您就知道const不应重新分配声明的变量。通过这种方式,我们的代码变得更具声明性并且更易于使用。
  • 我们强制执行不能重新分配变量的原则(JS引擎抛出错误)。这样,如果您不小心尝试重新分配一个不打算重新分配的变量,您可以在早期阶段检测到这一点(因为它已记录到控制台)。

警告:

尽管用 声明的变量const不能重新分配,但这并不意味着分配的对象不可变。例如:

const obj = {prop1: 1}

// we can still mutate the object assigned to the 
// variable declared with the const keyword
obj.prop1 = 10;
obj.prop2 = 2;

console.log(obj);

如果您还希望您的对象是不可变的,您可以使用Object.freeze()它来实现这一点。

于 2018-10-06T11:04:13.460 回答
5

let和_const

ES6let允许你声明一个范围限制在块中的变量(局部变量)。主要区别在于var变量的范围是整个封闭函数:

if (true) {
  var foo = 42; // scope globally
}

console.log(foo); // 42

let范围_

if (true) {
  let foo = 42; // scoped in block
}

console.log(foo); // ReferenceError: bar is not defined

var在函数范围内使用与使用相同let

function bar() {
  var foo = 42; // scoped in function
}

console.log(foo); // ReferenceError: bar is not defined

关键字将let变量声明附加到它包含的任何块的范围内。

申报令

let和之间的另一个区别var是声明/初始化顺序。访问在let其声明之前声明的变量会导致ReferenceError

console.log(a); // undefined
console.log(b); // ReferenceError: b is not defined
  
var a = 1;
let b = 2;

使用const

另一方面,使用 ES6const很像使用let,但是一旦分配了值,就无法更改。用作const不可变值以防止意外重新分配变量:

const num = 42;

try {
  num = 99;
} catch(err) {
  console.log(err);
  // TypeError: invalid assignment to const `number'

}

num; // 42

用于const分配现实生活中不变的变量(例如冷冻温度)。JavaScriptconst不是要制作不可更改的值,它与值无关,const是为了防止将另一个值重新分配给变量并将变量设置为只读。但是,值总是可以改变的:

const arr = [0, 1, 2];
arr[3] = 3; // [0, 1, 2, 3]

为防止值更改,请使用Object.freeze()

let arr = Object.freeze([0, 1, 2]);
arr[0] = 5;

arr; // [0, 1, 2]

使用循环let_For

真正闪耀的一个特殊情况let是在for循环的标题中:

for (let i = 0; i <= 5; i++) {
  console.log(i);
}

// 0 1 2 3 4 5

console.log(i); // ReferenceError, great! i is not global
于 2019-01-19T22:07:10.943 回答
3

让和常量

声明的变量letconst消除了提升的特定问题,因为它们的范围仅限于块,而不是函数。

如果使用letconst在代码块中声明变量(用大括号 { } 表示),则该变量将停留在所谓的临时死区中,直到变量的声明被处理。这种行为会阻止变量在被声明之前被访问。

使用 let 和 const 的规则

let并且const还有一些其他有趣的特性。

  • 声明的变量let可以重新分配,但不能在同一范围内重新声明。
  • 用 with 声明的变量const必须赋初值,但不能在同一个作用域内重新声明,也不能重新赋值。

用例

最大的问题是什么时候应该使用letand const?一般经验法则如下:

  • let当您计划将新值重新分配给变量时使用,并且
  • const当您不打算将新值重新分配给变量时使用。

由于const这是声明变量的最严格方法,因此建议您始终声明变量,const因为它会使您的代码更容易推理,因为您知道标识符在程序的整个生命周期内都不会改变。如果您发现需要更新或更改变量,则返回并将其constlet.

于 2018-08-31T06:29:21.423 回答
1
  • var 声明是全局作用域或函数作用域,而 let 和 const 是块作用域。

  • var 变量可以在其范围内更新和重新声明;let 变量可以更新但不能重新声明;const 变量不能更新也不能重新声明。

  • 它们都被提升到了范围的顶部。但是,虽然 var 变量是用 undefined 初始化的,但 let 和 const 变量不会被初始化。

  • 虽然 var 和 let 可以在不初始化的情况下声明,但 const 必须在声明期间初始化。

于 2020-08-02T19:32:11.140 回答
0

变量

The var keyword was introduced with JavaScript. 
It has global scope.    
It can be declared globally and can be accessed globally.   
Variable declared with var keyword can be re-declared and updated in the same scope.
Example:
function varGreeter(){
  var a = 10;        
  var a = 20; //a is replaced
  console.log(a);
}
varGreeter();

它被吊起。

Example:
{
  console.log(c); // undefined. 
  //Due to hoisting
  var c = 2;
}

The let keyword was added in ES6 (ES 2015) version of JavaScript.
It is limited to block scope.
It can be declared globally but cannot be accessed globally.
Variable declared with let keyword can be updated but not re-declared.
Example:
function varGreeter(){
  let a = 10;        
 let a = 20; //SyntaxError: 
 //Identifier 'a' has already been declared
  console.log(a);
}
varGreeter();

它没有被吊起。

Example:
{
  console.log(b); // ReferenceError: 
  //b is not defined
  let b = 3;
}

全局对象属性

  var no1 = "123";  // globally scoped
  let no2 = "789"; // globally scoped

  console.log(window.no1); // 123
  console.log(window.no2); // undefined

重新声明:

'使用严格';

  var name= "Keshav";
  var name= "Keshav Gera"; // No problem, 'name' is replaced.

  let surname= "Rahul Kumar";
  let surname= "Rahul Khan "; // SyntaxError: Identifier 'surname' has already been declared

吊装

function run() {
    console.log(name); // undefined
    var name= "Keshav";
    console.log(name); // Keshav
}

 run();

 function checkHoisting() {
     console.log(name); // ReferenceError
     let name= "Keshav";
     console.log(name); // Keshav
 }
 checkHoisting();

注意:如果是var,你会得到undefined,如果是let,你会得到reference error

常量

It allows you to be immutable with variables.

必须初始化 const 声明

const name; // ERROR: const declarations must be initialized

A const is block scoped like we saw with let:+

const num = 10;
if (true) {
 const num = 20; // Allowed as its a new variable limited to this `if` block
}
于 2020-06-26T10:40:17.007 回答
0

以下是我记下的一些笔记,对我在这个问题上有所帮助。还比较constletvar

这是关于var

// Var
// 1. var is hoisted to the top of the function, regardless of block
// 2. var can be defined as last line and will be hoisted to top of code block
// 3. for undefined var //output error is 'undefined' and code continues executing
// 4. trying to execute function with undefined variable
// Example: // log(myName); // output: ReferenceError: myName is not defined and code stops executing 

这是关于letconst

// Let and Const
// 1. use `const` to declare variables which won't change
// 2. `const` is used to initialize-once, read-only thereafter
// 3. use `let` to declare variables which will change
// 4. `let` or `const` are scoped to the "block", not the function
// 5. trying to change value of const and then console.logging result will give error
// const ANSWER = 42;
// ANSWER = 3.14159;
// console.log(ANSWER);
// Error statement will be "TypeError: Assignment to constant variable." and code will stop executing
// 6. `let` won't allow reference before definition
// function letTest2 () {
//   log(b);
//   let b = 3;}
// Error statement will be "ReferenceError: b is not defined." and code will stop executing
于 2018-07-19T12:21:25.673 回答
0
/*
// declaration of const in same block scope is not allowed
const a = 10;
const a = 15; //Redeclaration of const a Error
console.log(`const outer value `+a);
*/

/*
//declaration of const in different block scope is allowed
const a = 10;
console.log(`outer value of a `+a)
{
    const a = 15; //Redeclaration of const allowed in different block scope
    console.log(`ineer value of a `+a);
}
*/

/*
// re assigning const variable in any block scope is not allowed
const a = 10;
a = 15; //invalid assignment to const 'a'
{
    a = 15;  //invalid assignment to const 'a'
}
*/

/*
// let also can not be re declared in the same block scope
let a = 10;
let a = 15; //SyntaxError: redeclaration of let a
*/

/*
// let can be redeclared in different block scope
let a = 10;
{
    let a = 15; //allowed.
}
*/

/*
// let can be re assigned in same block or different block
let a = 10;
a = 15; //allowed for let but for const its not allowed.
*/

/*
let a = 10;
{
    a = 15; //allowed
}
*/
于 2021-08-11T13:20:28.477 回答