您的位置:首页 > 其它

ES6之let,const和块级作用域

2018-04-19 17:17 337 查看

var
 
第一个就是作用域的问题,var不是针对一个块级作用域,而是针对一个函数作用域。举个例子:
function runTowerExperiment(tower, startTime) {
var t = startTime;

tower.on("tick", function () {
... code that uses t ...
});
... more code ...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
这样是没什么问题的,因为回调函数中可以访问到变量t,但是如果我们在回调函数中再次命名了变量t呢?
function runTowerExperiment(tower, startTime) {
var t = startTime;

tower.on("tick", function () {
... code that uses t ...
if (bowlingBall.altitude() <= 0) {
var t = readTachymeter();
...
}
});
... more code ...
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
后者就会将前者覆盖。 
第二个就是循环的问题。 
看下面例子:
var messages = ["Meow!", "I'm a talking cat!", "Callbacks are fun!"];

for (var i = 0; i < messages.length; i++) {
setTimeout(function () {
document.write(messages[i]);
},i*1500);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
输出结果是:undefined
  • 1
因为for循环后,i置为3,所以访问不到其值。
let
 
为了解决这些问题,ES6提出了let语法。let可以在{},if,for里声明,其用法同var,但是作用域限定在块级。但是javascript中不是没有块级作用域吗?这个我们等会讲。还有一点很重要的就是let定义的变量不存在变量提升。 
变量提升. 
这里简单提一下什么叫做变量提升。
var v='Hello World';
(function(){
alert(v);
var v='I love you';
})()
  • 1
  • 2
  • 3
  • 4
  • 5
上面的代码输出结果为:
undefined
。 
为什么会这样呢?这就是因为变量提升,变量提升就是把变量的声明提升到函数顶部,比如:
(function(){
var a='One';
var b='Two';
var c='Three';
})()
实际上就是:
(function(){
var a,b,c;
a='One';
b='Two';
c='Three';
})()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
所以我们刚才的例子实际上是:
var v='Hello World';
(function(){
var v;
alert(v);
v='I love you';
})()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
所以就会返回
undefined
了。这也是var的一个问题,而我们使用let就不会出现这个问题。因为它会报语法错误:
{
console.log( a );   // undefined
console.log( b );   // ReferenceError!
var a;
let b;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
再来看看let的块级作用域。
function getVal(boo) {
if (boo) {
var val = 'red'
// ...
return val
} else {
// 这里可以访问 val
return null
}
// 这里也可以访问 val
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
同样的在for循环中:
function func(arr) {
for (var i = 0; i < arr.length; i++) {
// i ...
}
// 这里访问得到i
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
使用let后:
function func(arr) {
for (let i = 0; i < arr.length; i++) {
// i ...
}
// 这里访问不到i
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
也就是说,let只能在花括号内部起作用。
const
 
再来说说const,const代表一个值的常量索引。
const aa = 11;
alert(aa) //11
aa = 22;
alert(aa) //11
  • 1
  • 2
  • 3
  • 4
但是常量的值在垃圾回收前永远不能改变,所以需要谨慎使用。 
还有一条需要注意的就是和其他语言一样,常量的声明必须赋予初值。即使我们想要一个
undefined
的常量,也需要声明:
const a = undefined;
  • 1
块级作用域 
最后提一下刚才说到的块级作用域。 
在之前,javascript是没有块级作用域的,我们都是通过()来模拟块级作用域。
(function(){
//这里是块级作用域
})();
  • 1
  • 2
  • 3
但是在ES6中,{}就可以直接代码块级作用域。所以{}内的内容是不可以在{}外访问得到的。 
我们可以看看如下代码:
if (true) {
function foo() {
document.write( "1" );
}
}
else {
function foo() {
document.write( "2" );
}
}

foo();      //    在低版本ie上测试2  主流浏览器测试结果1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
在我们所认识的javascript里,这段代码的输出结果为2。这个叫做函数声明提升,不仅仅提升了函数名,也提升了函数的定义。如果你基础不扎实的话,可以看看这篇文章:深入理解javascript之IIFE 
但是在ES6里,这段代码或抛出
ReferenceErroe
错误。因为{}的块级作用域,导致外面访问不到foo(),也就是说函数声明和let定义变量一样,都被限制在块级作用域中了。

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: