Javascript 什么';“使用”的区别是什么;让我们;及;var";? 介绍了ECMAScript 6。

Javascript 什么';“使用”的区别是什么;让我们;及;var";? 介绍了ECMAScript 6。,javascript,scope,ecmascript-6,var,let,Javascript,Scope,Ecmascript 6,Var,Let,我听说它被描述为一个local变量,但我仍然不确定它的行为与var关键字有什么不同 有什么区别?。什么时候应该使用而不是var?下面是一个例子 let的工作原理非常类似于var。主要区别在于var变量的范围是整个封闭函数 维基百科上显示了哪些浏览器支持Javascript 1.7 请注意,只有Mozilla和Chrome浏览器支持它。IE、Safari和其他可能不这样做。有一些细微的区别-让范围界定的行为更像其他语言中变量范围界定的行为 e、 它的作用域是封闭块,它们在声明之前不存在,等等 但是

我听说它被描述为一个
local
变量,但我仍然不确定它的行为与
var
关键字有什么不同

有什么区别?。什么时候应该使用
而不是
var

下面是一个例子

let
的工作原理非常类似于
var
。主要区别在于
var
变量的范围是整个封闭函数

维基百科上显示了哪些浏览器支持Javascript 1.7


请注意,只有Mozilla和Chrome浏览器支持它。IE、Safari和其他可能不这样做。

有一些细微的区别-
让范围界定的行为更像其他语言中变量范围界定的行为

e、 它的作用域是封闭块,它们在声明之前不存在,等等

但是值得注意的是,
let
只是较新的Javascript实现的一部分,并且具有不同程度的作用域规则 主要区别在于范围规则。由
var
关键字声明的变量的作用域是直接函数体(因此是函数作用域),而
let
变量的作用域是由
{}
表示的直接封闭块(因此是块作用域)

let
关键字引入语言的原因是函数范围令人困惑,是JavaScript中错误的主要来源之一

请从以下方面查看此示例:

let
在对变量定义求值之前,不初始化变量。在初始化之前访问它们会导致
ReferenceError
。从块的开始到初始化被处理,变量被称为处于“时间死区”

function checkHoisting() {
  console.log(foo); // ReferenceError
  let foo = "Foo";
  console.log(foo); // Foo
}

checkHoisting();
创建全局对象属性 与
var
不同,在顶层,
let
不在全局对象上创建属性:

var foo = "Foo";  // globally scoped
let bar = "Bar"; // not allowed to be globally scoped

console.log(window.foo); // Foo
console.log(window.bar); // undefined
重声明 在严格模式下,
var
将允许您在同一范围内重新声明同一变量,而
let
将引发语法错误

'use strict';
var foo = "foo1";
var foo = "foo2"; // No problem, 'foo1' is replaced with 'foo2'.

let bar = "bar1"; 
let bar = "bar2"; // SyntaxError: Identifier 'bar' has already been declared

这里有一个例子来补充其他人已经写过的内容。假设您要创建一个函数数组,
adderFunctions
,其中每个函数接受一个数字参数,并返回参数和数组中函数索引的总和。尝试使用
var
关键字通过循环生成
adderFunctions
,不会像人们天真地期望的那样工作:

// An array of adder functions.
var adderFunctions = [];

for (var i = 0; i < 1000; i++) {
  // We want the function at index i to add the index to its argument.
  adderFunctions[i] = function(x) {
    // What is i bound to here?
    return x + i;
  };
}

var add12 = adderFunctions[12];

// Uh oh. The function is bound to i in the outer scope, which is currently 1000.
console.log(add12(8) === 20); // => false
console.log(add12(8) === 1008); // => true
console.log(i); // => 1000

// It gets worse.
i = -8;
console.log(add12(8) === 0); // => true
这次,
i
for
循环的每次迭代中都会反弹。现在,每个函数在创建函数时保留
i
的值,并且
adderFunctions
的行为与预期一致

现在,想象一下混合这两种行为,您可能会看到为什么不建议在同一脚本中混合较新的
let
const
与较旧的
var
。这样做可能会导致一些令人困惑的代码

const doubleAdderFunctions = [];

for (var i = 0; i < 1000; i++) {
    const j = i;
    doubleAdderFunctions[i] = x => x + i + j;
}

const add18 = doubleAdderFunctions[9];
const add24 = doubleAdderFunctions[12];

// It's not fun debugging situations like this, especially when the
// code is more complex than in this example.
console.log(add18(24) === 42); // => false
console.log(add24(18) === 42); // => false
console.log(add18(24) === add24(18)); // => false
console.log(add18(24) === 2018); // => false
console.log(add24(18) === 2018); // => false
console.log(add18(24) === 1033); // => true
console.log(add24(18) === 1030); // => true
constdoubleadderfunctions=[];
对于(变量i=0;i<1000;i++){
常数j=i;
双加法器函数[i]=x=>x+i+j;
}
const add18=双加法器函数[9];
const add24=双加法器函数[12];
//调试这样的情况并不有趣,尤其是当
//代码比本例中的代码更复杂。
console.log(add18(24)==42);//=>假的
console.log(add24(18)==42);//=>假的
console.log(add18(24)==add24(18));//=>假的
console.log(add18(24)==2018);//=>假的
console.log(add24(18)==2018);//=>假的
console.log(add18(24)==1033);//=>真的
console.log(add24(18)==1030);//=>真的
别让这种事发生在你身上。使用短绒

注意:这是一个教学示例,旨在演示
var
/
let
在循环中的行为以及易于理解的函数闭包。这将是一种可怕的数字相加方式。但是在现实世界中,在其他上下文中可能会遇到在匿名函数闭包中捕获数据的一般技术。YMMV


下面是一个例子来说明两者之间的区别(对chrome的支持刚刚开始):

如您所见,
var j
变量的值仍在for循环范围(块范围)之外,但
let i
变量在for循环范围之外未定义

“严格使用”;
console.log(“var:”);
对于(var j=0;j<2;j++){
控制台日志(j);
}
控制台日志(j);
console.log(“let:”);
for(设i=0;i<2;i++){
控制台日志(i);
}

控制台日志(i)
let
也可以用于避免闭包问题。它绑定新的值,而不是像下面的示例所示保留旧的引用


for(var i=1;i接受的答案缺少一点:

{
  let a = 123;
};

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

至少在VisualStudio2015中,TypeScript 1.5“var”允许在一个块中多个声明相同的变量名,而“let”则不允许

这不会生成编译错误:

var x = 1;
var x = 2;
这将:

let x = 1;
let x = 2;

以下两个功能是否可以显示差异:

function varTest() {
    var x = 31;
    if (true) {
        var x = 71;  // Same variable!
        console.log(x);  // 71
    }
    console.log(x);  // 71
}

function letTest() {
    let x = 31;
    if (true) {
        let x = 71;  // Different variable
        console.log(x);  // 71
    }
    console.log(x);  // 31
}
  • 变量不起重

    let
    不提升到它们出现的区块的整个范围。相比之下,
    var
    可以提升如下

    实际上,根据@Bergi

  • 垃圾收集

    <>代码块的范围>让与闭包和垃圾回收有关,以回收内存。考虑,

    function process(data) {
        //...
    }
    
    var hugeData = { .. };
    
    process(hugeData);
    
    var btn = document.getElementById("mybutton");
    btn.addEventListener( "click", function click(evt){
        //....
    });
    
    // print '5' 5 times
    for (var i = 0; i < 5; ++i) {
        setTimeout(function () {
            console.log(i);
        }, 1000);  
    }
    
    click
    处理程序回调根本不需要
    hugeData
    变量。理论上,在
    进程(…)
    运行后,庞大的数据结构
    hugeData
    可能会被垃圾收集。然而,一些JS引擎可能仍然需要保留这个庞大的结构,因为
    c
    
    function varTest() {
        var x = 31;
        if (true) {
            var x = 71;  // Same variable!
            console.log(x);  // 71
        }
        console.log(x);  // 71
    }
    
    function letTest() {
        let x = 31;
        if (true) {
            let x = 71;  // Different variable
            console.log(x);  // 71
        }
        console.log(x);  // 31
    }
    
    {
       console.log(cc); // undefined. Caused by hoisting
       var cc = 23;
    }
    
    {
       console.log(bb); // ReferenceError: bb is not defined
       let bb = 23;
    }
    
    function process(data) {
        //...
    }
    
    var hugeData = { .. };
    
    process(hugeData);
    
    var btn = document.getElementById("mybutton");
    btn.addEventListener( "click", function click(evt){
        //....
    });
    
    function process(data) {
        //...
    }
    
    { // anything declared inside this block can be garbage collected
        let hugeData = { .. };
        process(hugeData);
    }
    
    var btn = document.getElementById("mybutton");
    btn.addEventListener( "click", function click(evt){
        //....
    });
    
    // print '5' 5 times
    for (var i = 0; i < 5; ++i) {
        setTimeout(function () {
            console.log(i);
        }, 1000);  
    }
    
    // print 1, 2, 3, 4, 5. now
    for (let i = 0; i < 5; ++i) {
        setTimeout(function () {
            console.log(i);
        }, 1000);  
    }
    
    // i IS NOT known here
    // j IS NOT known here
    // k IS known here, but undefined
    // l IS NOT known here
    
    function loop(arr) {
        // i IS known here, but undefined
        // j IS NOT known here
        // k IS known here, but has a value only the second time loop is called
        // l IS NOT known here
    
        for( var i = 0; i < arr.length; i++ ) {
            // i IS known here, and has a value
            // j IS NOT known here
            // k IS known here, but has a value only the second time loop is called
            // l IS NOT known here
        };
    
        // i IS known here, and has a value
        // j IS NOT known here
        // k IS known here, but has a value only the second time loop is called
        // l IS NOT known here
    
        for( let j = 0; j < arr.length; j++ ) {
            // i IS known here, and has a value
            // j IS known here, and has a value
            // k IS known here, but has a value only the second time loop is called
            // l IS NOT known here
        };
    
        // i IS known here, and has a value
        // j IS NOT known here
        // k IS known here, but has a value only the second time loop is called
        // l IS NOT known here
    }
    
    loop([1,2,3,4]);
    
    for( var k = 0; k < arr.length; k++ ) {
        // i IS NOT known here
        // j IS NOT known here
        // k IS known here, and has a value
        // l IS NOT known here
    };
    
    for( let l = 0; l < arr.length; l++ ) {
        // i IS NOT known here
        // j IS NOT known here
        // k IS known here, and has a value
        // l IS known here, and has a value
    };
    
    loop([1,2,3,4]);
    
    // i IS NOT known here
    // j IS NOT known here
    // k IS known here, and has a value
    // l IS NOT known here
    
    function printnums()
    {
        // i is not accessible here
        for(let i = 0; i <10; i+=)
        {
           console.log(i);
        }
        // i is not accessible here
    
        // j is accessible here
        for(var j = 0; j <10; j++)
        {
           console.log(j);
        }
        // j is accessible here
    }
    
    (() => {
        var count = 0;
    
        for (let i = 0; i < 2; ++i) {
            for (let i = 0; i < 2; ++i) {
                for (let i = 0; i < 2; ++i) {
                    console.log(count++);
                }
            }
        }
    })();
    
    (() => {
        var count = 0;
    
        for (var i = 0; i < 2; ++i) {
            for (var i = 0; i < 2; ++i) {
                for (var i = 0; i < 2; ++i) {
                    console.log(count++);
                }
            }
        }
    })();
    
        let statistics = [16, 170, 10];
        let [age, height, grade] = statistics;
    
        console.log(height)
    
        let x = 120,
        y = 12;
        [x, y] = [y, x];
        console.log(`x: ${x} y: ${y}`);
    
        let node = {
                       type: "Identifier",
                       name: "foo"
                   };
    
        let { type, name, value } = node;
    
        console.log(type);      // "Identifier"
        console.log(name);      // "foo"
        console.log(value);     // undefined
    
        let node = {
            type: "Identifier"
        };
    
        let { type: localType, name: localName = "bar" } = node;
    
        console.log(localType);     // "Identifier"
        console.log(localName);     // "bar"
    
    let jar = {
        numberOfCookies: 10,
        get cookies() {
            return this.numberOfCookies;
        },
        set cookies(value) {
            this.numberOfCookies = value;
        }
    };
    
    console.log(jar.cookies)
    jar.cookies = 7;
    
    console.log(jar.cookies)
    
    var SomeConstructor;
    
    {
        let privateScope = {};
    
        SomeConstructor = function SomeConstructor () {
            this.someProperty = "foo";
            privateScope.hiddenProperty = "bar";
        }
    
        SomeConstructor.prototype.showPublic = function () {
            console.log(this.someProperty); // foo
        }
    
        SomeConstructor.prototype.showPrivate = function () {
            console.log(privateScope.hiddenProperty); // bar
        }
    
    }
    
    var myInstance = new SomeConstructor();
    
    myInstance.showPublic();
    myInstance.showPrivate();
    
    console.log(privateScope.hiddenProperty); // error
    
    var globalVariable = 42;
    let blockScopedVariable = 43;
    
    console.log(globalVariable); // 42
    console.log(blockScopedVariable); // 43
    
    console.log(this.globalVariable); // 42
    console.log(this.blockScopedVariable); // undefined
    
    (() => {
      var functionScopedVariable = 42;
      let blockScopedVariable = 43;
    
      console.log(functionScopedVariable); // 42
      console.log(blockScopedVariable); // 43
    })();
    
    console.log(functionScopedVariable); // ReferenceError: functionScopedVariable is not defined
    console.log(blockScopedVariable); // ReferenceError: blockScopedVariable is not defined
    
    {
      var globalVariable = 42;
      let blockScopedVariable = 43;
      console.log(globalVariable); // 42
      console.log(blockScopedVariable); // 43
    }
    
    console.log(globalVariable); // 42
    console.log(blockScopedVariable); // ReferenceError: blockScopedVariable is not defined
    
    for (var i = 0; i < 3; i++) {
      var j = i * 2;
    }
    console.log(i); // 3
    console.log(j); // 4
    
    for (let k = 0; k < 3; k++) {
      let l = k * 2;
    }
    console.log(typeof k); // undefined
    console.log(typeof l); // undefined
    // Trying to do console.log(k) or console.log(l) here would throw a ReferenceError.
    
    // Logs 3 thrice, not what we meant.
    for (var i = 0; i < 3; i++) {
      setTimeout(() => console.log(i), 0);
    }
    
    // Logs 0, 1 and 2, as expected.
    for (let j = 0; j < 3; j++) {
      setTimeout(() => console.log(j), 0);
    }
    
    console.log(noTDZ); // undefined
    var noTDZ = 43;
    console.log(hasTDZ); // ReferenceError: hasTDZ is not defined
    let hasTDZ = 42;
    
    var a;
    var a; // Works fine.
    
    let b;
    let b; // SyntaxError: Identifier 'b' has already been declared
    
    var c;
    let c; // SyntaxError: Identifier 'c' has already been declared
    
    const a = 42;
    a = 43; // TypeError: Assignment to constant variable.
    
    const obj = {};
    obj.a = 42;
    console.log(obj.a); // 42
    
    const a; // SyntaxError: Missing initializer in const declaration
    
    function varTest() {
      var x = 1;
      if (true) {
        var x = 2;  // same variable!
        console.log(x);  // 2
      }
      console.log(x);  // 2
    }
    
    function letTest() {
      let x = 1;
      if (true) {
        let x = 2;  // different variable
        console.log(x);  // 2
      }
      console.log(x);  // 1
    }`
    
    var x = 'global';
    let y = 'global';
    console.log(this.x); // "global"
    console.log(this.y); // undefined
    
    var a = 1;
    var b = 2;
    
    if (a === 1) {
      var a = 11; // the scope is global
      let b = 22; // the scope is inside the if-block
    
      console.log(a);  // 11
      console.log(b);  // 22
    } 
    
    console.log(a); // 11
    console.log(b); // 2
    
    {
        let x = 1;
    }
    console.log(`x is ${x}`);  // ReferenceError during parsing: "x is not defined".
    
    {
        x = x + 1;  // ReferenceError during parsing: "x is not defined".
        let x;
        console.log(`x is ${x}`);  // Never runs.
    }
    
    let x = 1;
    let x = 2;  // SyntaxError: Identifier 'x' has already been declared
    
    var button = "I cause accidents because my name is too common.";
    let link = "Though my name is common, I am harder to access from other JS files.";
    console.log(link);  // OK
    console.log(window.link);  // undefined (GOOD!)
    console.log(window.button);  // OK
    
    for (let i = 0; i < 5; i++) {
        console.log(`i is ${i}`), 125/*ms*/);
    }
    
    i is 0
    i is 1
    i is 2
    i is 3
    i is 4
    
    for (let i = 0; i < 5; i++) {
        setTimeout(_ => console.log(`i is ${i}`), 125/*ms*/);
    }
    
    for (var i = 0; i < 5; i++) {
        setTimeout(_ => console.log(`i is ${i}`), 125/*ms*/);
    }
    
    i is 5
    i is 5
    i is 5
    i is 5
    i is 5
    
    function varTest() {
      var x = 1;
      if (true) {
        var x = 2;  // same variable!
        console.log(x);  // 2
      }
      console.log(x);  // 2
    }
    
    function letTest() {
      let x = 1;
      if (true) {
        let x = 2;  // different variable
        console.log(x);  // 2
      }
      console.log(x);  // 1
    }
    
    function a(){
        { // this is the Max Scope for let variable
            let x = 12;
        }
        console.log(x);
    }
    a(); // Uncaught ReferenceError: x is not defined
    
    function a(){ // this is the Max Scope for var variable
        { 
            var x = 12;
        }
        console.log(x);
    }
    a(); // 12
    
    for (let i = 0; i < 10 ; i++) {
        setTimeout(
            function a() {
                console.log(i); //print 0 to 9, that is literally AWW!!!
            }, 
            100 * i);
    }
    
    for (var i = 0; i < 10 ; i++) {
        setTimeout(
            function a() {
                console.log(i); //print 10 times 10
            }, 
            100 * i);
    }
    
    function testVar () {
      if(true) {
        var foo = 'foo';
      }
    
      console.log(foo);
    }
    
    testVar();  
    // logs 'foo'
    
    
    function testLet () {
      if(true) {
        let bar = 'bar';
      }
    
      console.log(bar);
    }
    
    testLet(); 
    // reference error
    // bar is scoped to the block of the if statement 
    
    console.log(letVar);
    
    let letVar = 10;
    // referenceError, the variable doesn't get hoisted
    
    console.log(varVar);
    
    var varVar = 10;
    // logs undefined, the variable gets hoisted
    
    var bar = 5;
    let foo  = 10;
    
    console.log(bar); // logs 5
    console.log(foo); // logs 10
    
    console.log(window.bar);  
    // logs 5, variable added to window object
    
    console.log(window.foo);
    // logs undefined, variable not added to window object
    
    (function timer() {
        for(var i = 0; i <= 5; i++) {
            setTimeout(function notime() { console.log(i); }, i * 1000);
        }
    })();
    
    
       Stack            VariableEnvironment //one VariablEnvironment for timer();
                                           // when the timer is out - the value will be the same value for each call
    5. [setTimeout, i]  [i=5] 
    4. [setTimeout, i]  
    3. [setTimeout, i]
    2. [setTimeout, i]
    1. [setTimeout, i]
    0. [setTimeout, i]
    
    ####################    
    
    (function timer() {
        for (let i = 0; i <= 5; i++) {
            setTimeout(function notime() { console.log(i); }, i * 1000);
        }
    })();
    
       Stack           LexicalEnvironment - each iteration has a new lexical environment
    5. [setTimeout, i]  [i=5]       
                          LexicalEnvironment 
    4. [setTimeout, i]    [i=4]     
                            LexicalEnvironment 
    3. [setTimeout, i]      [i=3]       
                             LexicalEnvironment 
    2. [setTimeout, i]       [i=2]
                               LexicalEnvironment 
    1. [setTimeout, i]         [i=1]
                                 LexicalEnvironment 
    0. [setTimeout, i]           [i=0]
    
    function test() {
        for(var z = 0; z < 69; z++) {
            //todo
        }
        //z is visible outside the loop
    }
    
    function test() {
        for(let z = 0; z < 69; z++) {
            //todo
        }
        //z is not defined :(
    }
    
    var cat = "cat";
    let dog = "dog";
    
    var animals = () => {
        var giraffe = "giraffe";
        let lion = "lion";
    
        console.log(cat);  //will print 'cat'.
        console.log(dog);  //will print 'dog', because dog was declared outside this function (like var cat).
    
        console.log(giraffe); //will print 'giraffe'.
        console.log(lion); //will print 'lion', as lion is within scope.
    }
    
    console.log(giraffe); //will print 'giraffe', as giraffe is a global variable (var).
    console.log(lion); //will print UNDEFINED, as lion is a 'let' variable and is now out of scope.
    
    let gfoo = 123;
    if (true) {
        let gfoo = 456;
    }
    console.log(gfoo); // 123
    
    var hfoo = 123;
    if (true) {
        var hfoo = 456;
    }
    console.log(hfoo); // 456
    
    for (let i = 0; i < 5; i++) {
      // i accessible ✔️
    }
    // i not accessible ❌
    
    for (var i = 0; i < 5; i++) {
      // i accessible ✔️
    }
    // i accessible ✔️
    
    let variableName = 'a';
    eval("let " + variableName + '= 10;');
    console.log(a);   // this doesn't work
    
    var variableName = 'a';
    eval("var " + variableName + '= 10;');
    console.log(a);   // this works