让ES6中的关键字

时间:2018-06-19 08:52:18

标签: ecmascript-6

请解释两个代码之间的区别。为什么两者的输出都不同。

'use strict';
let printNumTwo;
for (let i = 0; i < 3; i++) {
  if (i === 2) {
    printNumTwo = function() {
      return i;
    };
  }
}
console.log(printNumTwo());

'use strict';
let printNumTwo;
let i;
for (i = 0; i < 3; i++) {
  if (i === 2) {
    printNumTwo = function() {
      return i;
    };
  }
}
console.log(printNumTwo());

2 个答案:

答案 0 :(得分:3)

区别在于声明i的范围。

在循环块范围内声明i

'use strict';
let printNumTwo;
for (let i = 0; i < 3; i++) { // block scope
  // each time we have new variable i
  if (i === 2) { // block scope
    printNumTwo = function() {
      return i; // captures the one that was equal 2
    };
  }
}

// console.log(i) // throws ReferenceError
console.log(printNumTwo());

在全局范围内声明i

'use strict';
let printNumTwo;
let i; // globally scoped
for (i = 0; i < 3; i++) {
  if (i === 2) {
    printNumTwo = function() {
      return i; // captures globally scoped i which will be mutated i++
    };
  }
}
console.log(i) // prints 3
console.log(printNumTwo());

UPD一些文档 Spec

  

13.7.4.8运行时语义:ForBodyEvaluation ( test, increment, stmt, perIterationBindings, labelSet )抽象操作   ForBodyEvaluation with arguments test,increment,stmt,   perIterationBindings和labelSet按如下方式执行:

     
      
  1. V成为undefined
  2.   
  3. 表演? CreatePerIterationEnvironment(perIterationBindings)
  4.   
  5. 重复,
  6.         

    ...

         

    即表演? CreatePerIterationEnvironment(perIterationBindings)

         

    F。如果increment不是[空],那么......

基本上在PerIterationEnvironment部分之前创建了新的increment。因此函数将捕获i === 2

答案 1 :(得分:1)

我只会解释第一个例子,因为第二个例子很明显

'use strict';
let printNumTwo;
for (let i = 0; i < 3; i++) {
  if (i === 2) { // block scope
    printNumTwo = function() {
      return i;
    };
  }
}

console.log(i)
console.log(printNumTwo());

当你使用let inside for循环时,这意味着变量i仅在for scope中定义,所以在i等于2的范围内我们设置变量printNumTwo,当我们再次执行i ++时,我改变了它值为3,但不会更改其在for范围内的值,它仍然等于2 ,这意味着如果您想以某种方式访问​​i值,它总是等于2

for (let i = 0; i < 3; i++) {
  console.log(i) // prints 0,1,2 
}

console.log(i) // undefined

要记住的是,即使我等于2并且我们做了++,它也不会在for scope中改变它的值,因为我是用let定义的