协慌网

登录 贡献 社区

使用 “let” 和“var”在 JavaScript 中声明变量有什么区别?

ECMAScript 6 引入let语句 。我听说它被描述为 “本地” 变量,但我仍然不太确定它与var关键字的行为方式有何不同。

有什么区别?什么时候应该let在使用var

答案

区别在于范围界定。 var的作用范围是最接近的功能块和let可以被限制在最近的封闭块,其可以是比功能块小。如果在任何区域之外,两者都是全球

此外,使用let声明的变量在它们的封闭块中声明之前是不可访问的。如演示中所示,这将引发 ReferenceError 异常。

演示

var html = '';

write('#### global ####\n');
write('globalVar: ' + globalVar); //undefined, but visible

try {
  write('globalLet: ' + globalLet); //undefined, *not* visible
} catch (exception) {
  write('globalLet: exception');
}

write('\nset variables');

var globalVar = 'globalVar';
let globalLet = 'globalLet';

write('\nglobalVar: ' + globalVar);
write('globalLet: ' + globalLet);

function functionScoped() {
  write('\n#### function ####');
  write('\nfunctionVar: ' + functionVar); //undefined, but visible

  try {
    write('functionLet: ' + functionLet); //undefined, *not* visible
  } catch (exception) {
    write('functionLet: exception');
  }

  write('\nset variables');

  var functionVar = 'functionVar';
  let functionLet = 'functionLet';

  write('\nfunctionVar: ' + functionVar);
  write('functionLet: ' + functionLet);
}

function blockScoped() {
  write('\n#### block ####');
  write('\nblockVar: ' + blockVar); //undefined, but visible

  try {
    write('blockLet: ' + blockLet); //undefined, *not* visible
  } catch (exception) {
    write('blockLet: exception');
  }

  for (var blockVar = 'blockVar', blockIndex = 0; blockIndex < 1; blockIndex++) {
    write('\nblockVar: ' + blockVar); // visible here and whole function
  };

  for (let blockLet = 'blockLet', letIndex = 0; letIndex < 1; letIndex++) {
    write('blockLet: ' + blockLet); // visible only here
  };

  write('\nblockVar: ' + blockVar);

  try {
    write('blockLet: ' + blockLet); //undefined, *not* visible
  } catch (exception) {
    write('blockLet: exception');
  }
}

function write(line) {
  html += (line ? line : '') + '<br />';
}

functionScoped();
blockScoped();

document.getElementById('results').innerHTML = html;
<pre id="results"></pre>

全球:

在功能块之外使用它们非常相似。

let me = 'go';  // globally scoped
var i = 'able'; // globally scoped

但是,使用let定义的全局变量不会作为属性添加到全局window对象上,就像使用var定义的那样。

console.log(window.me); // undefined
console.log(window.i); // 'able'

功能:

在功能块中使用时它们是相同的。

function ingWithinEstablishedParameters() {
    let terOfRecommendation = 'awesome worker!'; //function block scoped
    var sityCheerleading = 'go!'; //function block scoped
}

块:

这是区别。 let仅在for()循环中可见, var对整个函数可见。

function allyIlliterate() {
    //tuce is *not* visible out here

    for( let tuce = 0; tuce < 5; tuce++ ) {
        //tuce is only visible in here (and in the for() parentheses)
        //and there is a separate tuce variable for each iteration of the loop
    }

    //tuce is *not* visible out here
}

function byE40() {
    //nish *is* visible out here

    for( var nish = 0; nish < 5; nish++ ) {
        //nish is visible to the whole function
    }

    //nish *is* visible out here
}

重声明:

假设严格模式, var将允许您在同一范围内重新声明相同的变量。另一方面, let不会:

'use strict';
let me = 'foo';
let me = 'bar'; // SyntaxError: Identifier 'me' has already been declared
'use strict';
var me = 'foo';
var me = 'bar'; // No problem, `me` is replaced.

let也可以用来避免闭包问题。它绑定了新的价值,而不是保留旧的参考,如下面的例子所示。

DEMO

for(var i = 1; i < 6; i++) {
  document.getElementById('my-element' + i)
    .addEventListener('click', function() { alert(i) })
}

上面的代码演示了一个典型的 JavaScript 闭包问题对i变量的引用存储在单击处理程序闭包中,而不是i的实际值。

每个单击处理程序都将引用同一个对象,因为只有一个计数器对象可以容纳 6,因此每次单击时会得到 6 个。

一般的解决方法是将它包装在一个匿名函数中并将i作为参数传递。现在也可以通过使用let代替var来避免这些问题,如下面的代码所示。

演示 (在 Chrome 和 Firefox 50 中测试)

'use strict';

for(let i = 1; i < 6; i++) {
  document.getElementById('my-element' + i)
    .addEventListener('click', function() { alert(i) })
}

以下是let关键字解释和一些示例。

让我的工作非常像 var。主要区别在于 var 变量的范围是整个封闭函数

维基百科上的这个表显示了哪些浏览器支持 Javascript 1.7。

请注意,只有 Mozilla 和 Chrome 浏览器支持它。 IE,Safari 和其他人可能没有。