3.5 KiB
id | title | challengeType | forumTopicId | dashedName |
---|---|---|---|---|
587d7b87367417b2b2512b40 | 比较 var 和 let 关键字的作用域 | 1 | 301195 | compare-scopes-of-the-var-and-let-keywords |
--description--
使用 var
关键字来声明一个变量的时候,这个变量会被声明成全局变量,或是函数内的局部变量。
let
关键字的作用与此类似,但会有一些额外的特性。 如果在代码块、语句或表达式中使用关键字 let
声明变量,这个变量的作用域就被限制在当前的代码块、语句或表达式之中。
举个例子:
var numArray = [];
for (var i = 0; i < 3; i++) {
numArray.push(i);
}
console.log(numArray);
console.log(i);
这里控制台将显示值 [0, 1, 2]
和 3
。
因为使用了 var
关键字,i
被声明为全局变量。 所以当 i++
执行时,它会更新全局变量。 这个代码和下方的代码类似:
var numArray = [];
var i;
for (i = 0; i < 3; i++) {
numArray.push(i);
}
console.log(numArray);
console.log(i);
这里控制台将显示值 [0, 1, 2]
和 3
。
如果你创建一个函数,将它存储起来,稍后在使用 i
变量的 for
循环中使用。这么做可能会出现问题。 这是因为存储的函数会总是指向更新后的全局 i
变量的值。
var printNumTwo;
for (var i = 0; i < 3; i++) {
if (i === 2) {
printNumTwo = function() {
return i;
};
}
}
console.log(printNumTwo());
这里控制台将显示值 3
。
可以看到,printNumTwo()
打印了 3,而不是 2。 这是因为赋值给 i
的值已经更新,printNumTwo()
返回全局的 i
,而不是在 for 循环中创建函数时 i
的值。 let
关键字就不会出现这种现象:
let printNumTwo;
for (let i = 0; i < 3; i++) {
if (i === 2) {
printNumTwo = function() {
return i;
};
}
}
console.log(printNumTwo());
console.log(i);
在这里控制台将显示值 2
和一个错误提示 i is not defined
。
i
未定义,因为它没有在全局范围内声明。 它只在 for
循环语句中被声明。 printNumTwo()
返回了正确的值,因为 let
关键字在循环语句中使 i
变量产生了三个不同的值(分别为 0、1、2)。
--instructions--
修改这段代码,使 if
语句中声明的 i
变量与在函数的第一行声明的 i
变量是彼此独立的。 请注意不要在你的代码的任何地方使用 var
关键字。
这个练习旨在表明使用 var
与 let
关键字声明变量时作用域之间的区别。 当编写类似这个练习中的函数的时候,通常来说最好使用不同的变量名,以避免混淆。
--hints--
代码中不应该出现 var
。
(getUserInput) => assert(!getUserInput('index').match(/var/g));
if
语句中声明的变量 i
应该等于字符串 block scope
。
(getUserInput) =>
assert(
getUserInput('index').match(/(i\s*=\s*).*\s*.*\s*.*\1('|")block\s*scope\2/g)
);
checkScope()
应该返回字符串 function scope
。
assert(checkScope() === 'function scope');
--seed--
--seed-contents--
function checkScope() {
var i = 'function scope';
if (true) {
i = 'block scope';
console.log('Block scope i is: ', i);
}
console.log('Function scope i is: ', i);
return i;
}
--solutions--
function checkScope() {
let i = 'function scope';
if (true) {
let i = 'block scope';
console.log('Block scope i is: ', i);
}
console.log('Function scope i is: ', i);
return i;
}