繁体   English   中英

'let' 和 'const' ECMAScript 2015 (ES6) 有什么区别?

[英]What is the difference between 'let' and 'const' ECMAScript 2015 (ES6)?

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

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能力。

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

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

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

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

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

其次,像 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() 但是,这只会使对象本身成为只读的; 对象属性的值仍然可以改变。

您所看到的只是一个实施错误。 根据 const 上的const规范 wikiconst是:

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

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

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

  • 在编程中使用块作用域。
  • 对于每个块,让我们创建自己的新范围,您无法在该块之外访问。
  • 值可以根据需要更改多次。
  • 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
}

letconst

ES6 let允许你声明一个范围限制在块中的变量(局部变量)。 主要区别在于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: foo is not defined

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

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

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

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

申报令

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

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

使用const

另一方面,使用 ES6 的const很像使用let ,但是一旦赋值,就不能改变了。 使用const作为不可变值,以防止意外重新分配变量:

const num = 42;

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

}

num; // 42

使用const分配现实生活中不变的变量(例如冷冻温度)。 JavaScript const不是要制作不可更改的值,它与值无关, 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]

使用letFor循环

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

概括:

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

  • 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()来实现这一点。

让和常量

letconst声明的变量消除了提升的特定问题,因为它们的作用域是块,而不是函数。

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

使用 let 和 const 的规则

letconst还有一些其他有趣的属性。

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

用例

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

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

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

  • var 声明是全局作用域或函数作用域,而 let 和 const 是块作用域。

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

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

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

以下是我记下的一些笔记,对我在这个问题上有所帮助。 还将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

变量

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
}
/*
// 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
}
*/

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM