Javascript 变量是用let还是const声明的?

Javascript 变量是用let还是const声明的?,javascript,ecmascript-6,constants,let,hoisting,Javascript,Ecmascript 6,Constants,Let,Hoisting,我使用ES6已经有一段时间了,我注意到当使用var声明的变量按照预期被提升时 console.log(typeof name); // undefined var name = "John"; …使用声明的变量let或const似乎在提升方面存在一些问题: console.log(typeof name); // ReferenceError let name = "John"; 及 这是否意味着使用let或const声明的变量不被提升?这到底是怎么回事?在这个问题上,let和const之间

我使用ES6已经有一段时间了,我注意到当使用
var
声明的变量按照预期被提升时

console.log(typeof name); // undefined
var name = "John";
…使用
声明的变量let
const
似乎在提升方面存在一些问题:

console.log(typeof name); // ReferenceError
let name = "John";

这是否意味着使用
let
const
声明的变量不被提升?这到底是怎么回事?在这个问题上,
let
const
之间有什么区别吗?

引用ECMAScript 6(ECMAScript 2015)规范的第节

变量是在实例化其包含词法的环境时创建的,但在对变量的词法绑定进行求值之前,可能无法以任何方式访问


因此,为了回答您的问题,是的,
常量
提升,但在运行时评估实际声明之前,您无法访问它们。

@thefourtheye正确地说,这些变量在声明之前无法访问。然而,它比这要复杂一点

使用
let
const
声明的变量是否未提升?这到底是怎么回事

所有声明(
var
let
const
函数
函数*
在JavaScript中被“提升”。这意味着,如果在某个范围内声明了名称,则在该范围内,标识符将始终引用该特定变量:

x = "global";
// function scope:
(function() {
    x; // not "global"

    var/let/… x;
}());
// block scope (not for `var`s):
{
    x; // not "global"

    let/const/… x;
}
函数和块作用域1都是如此

var
/
函数
/
函数*
声明和
let
/
常量
/
声明之间的区别在于初始化
在作用域顶部创建绑定时,前者使用
未定义的
或(生成器)函数进行初始化。但是,词汇声明的变量保持未初始化状态。这意味着当您尝试访问它时,会引发
ReferenceError
异常。只有在对
let
/
const
/
语句求值时,才会对其进行初始化,前面(上面)的所有内容都称为暂时死区

注意a
让y
语句用
未定义的
初始化变量,如
let y=undefined会有

时间死区不是一个语法位置,而是变量(范围)创建和初始化之间的时间。在声明上方的代码中引用变量不是错误,只要该代码未执行(例如,函数体或简单的死代码),并且如果您在初始化之前访问变量,即使访问代码低于声明,也会引发异常(例如,在过早调用的已挂起功能声明中)

在这件事上,
let
const
之间有什么区别吗

不,就提升而言,它们的工作原理是相同的。它们之间唯一的区别是
常量
蚂蚁必须并且只能在声明的初始值设定部分分配(
const one=1;
,两者都
const one;
以及以后类似
one=2
的重新分配无效)


1:
var
声明仍然只在功能级别上起作用,当然
ES6
引入了
Let
变量,这些变量产生了
块级别的作用域
。在
ES5
之前,我们没有
块级别的作用域
,因此在块内部声明的变量总是
hoisted
到功能级别范围

基本上,
Scope
指的是您的变量在程序中的可见位置,这决定了您可以在哪里使用您声明的变量。在
ES5
中,我们有
全局作用域、函数作用域和try/catch作用域
,在
ES6
中,我们还可以使用Let获得块级作用域

  • 当您使用
    var
    关键字定义变量时,从定义它的那一刻起就知道整个函数
  • 当您使用
    let
    语句定义变量时,它只在所定义的块中已知

     function doSomething(arr){
         //i is known here but undefined
         //j is not known here
    
         console.log(i);
         console.log(j);
    
         for(var i=0; i<arr.length; i++){
             //i is known here
         }
    
         //i is known here
         //j is not known here
    
         console.log(i);
         console.log(j);
    
         for(let j=0; j<arr.length; j++){
             //j is known here
         }
    
         //i is known here
         //j is not known here
    
         console.log(i);
         console.log(j);
     }
    
     doSomething(["Thalaivar", "Vinoth", "Kabali", "Dinesh"]);
    
    第一个
    for
    循环始终打印最后一个值,使用
    let
    它创建一个新范围并绑定新值,打印我们
    1,2,3,4,5

    谈到
    常量
    ,它的工作原理基本上类似于
    let
    ,唯一的区别是它们的值不能更改。在常量中允许变异,但不允许重新分配。

    for(var i=1; i<6; i++){
       setTimeout(function(){
          console.log(i);
       },1000)
    }
    
    for(let i=1; i<6; i++){
       setTimeout(function(){
          console.log(i);
       },1000)
    }
    
    const foo = {};
    foo.bar = 42;
    console.log(foo.bar); //works
    
    const name = []
    name.push("Vinoth");
    console.log(name); //works
    
    const age = 100;
    age = 20; //Throws Uncaught TypeError: Assignment to constant variable.
    
    console.log(age);
    
    如果常数引用一个
    对象
    ,它将始终引用
    对象
    ,但是
    对象
    本身可以更改(如果它是可变的)。如果你想拥有一个不可变的
    对象
    ,你可以从

    在ECMAScript 2015中,
    let
    const
    被提升但未初始化。在变量声明之前引用块中的变量会导致
    ReferenceError
    ,因为从块的开始到声明被处理之前,变量处于“暂时死区”

    console.log(x); // ReferenceError
    let x = 3;
    

    在es6中,当我们使用let或const时,我们必须在使用它们之前声明变量。 例1-

    例2-

    // this code works as variable j is declared before it is used.
    function doSmth() {
    j = 9;
    }
    let j;
    doSmth();
    console.log(j); // 9
    
    根据ECMAScript®2021 Let和Const声明
    • 让和const声明定义作用于正在运行的执行上下文的词典环境的变量
    • 变量是在实例化其包含的环境记录时创建的,但在对变量的字典绑定求值之前,不能以任何方式访问变量
    • 由带有初始值设定项的词典绑定定义的变量被赋予其I的值
      console.log(x); // ReferenceError
      let x = 3;
      
      // this will work
      u = 10;
      var u;
      
      // this will give an error 
      k = 10;
      let k;  // ReferenceError: Cannot access 'k' before initialization.
      
      // this code works as variable j is declared before it is used.
      function doSmth() {
      j = 9;
      }
      let j;
      doSmth();
      console.log(j); // 9