ES6之let,const和块级作用域

var
第一个就是作用域的问题,var不是针对一个块级作用域,而是针对一个函数作用域。举个例子:

function runTowerExperiment(tower, startTime) {
  var t = startTime;

  tower.on("tick", function () {
    ... code that uses t ...
  });
  ... more code ...
}

这样是没什么问题的,因为回调函数中可以访问到变量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 ...
}

后者就会将前者覆盖。
第二个就是循环的问题。
看下面例子:

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);
输出结果是:undefined 

因为for循环后,i置为3,所以访问不到其值。

let
为了解决这些问题,ES6提出了let语法。let可以在{},if,for里声明,其用法同var,但是作用域限定在块级。但是javascript中不是没有块级作用域吗?这个我们等会讲。还有一点很重要的就是let定义的变量不存在变量提升。
变量提升.
这里简单提一下什么叫做变量提升。

var v='Hello World'; 
(function(){ 
    alert(v); 
    var v='I love you'; 
})()

上面的代码输出结果为:undefined
为什么会这样呢?这就是因为变量提升,变量提升就是把变量的声明提升到函数顶部,比如:

(function(){ 
    var a='One'; 
    var b='Two'; 
    var c='Three'; 
})()
实际上就是:
(function(){ 
    var a,b,c; 
    a='One'; 
    b='Two'; 
    c='Three'; 
})()

所以我们刚才的例子实际上是:

var v='Hello World'; 
(function(){ 
    var v;
    alert(v); 
    v='I love you'; 
})()

所以就会返回undefined了。

这也是var的一个问题,而我们使用let就不会出现这个问题。因为它会报语法错误:

{     
    console.log( a );   // undefined
    console.log( b );   // ReferenceError!      
    var a;
    let b;     
}

再来看看let的块级作用域。

function getVal(boo) {
    if (boo) {
        var val = 'red'
        // ...
        return val
    } else {
        // 这里可以访问 val
        return null
    }
    // 这里也可以访问 val
}

同样的在for循环中:

function func(arr) {
    for (var i = 0; i < arr.length; i++) {
        // i ...
    }
    // 这里访问得到i
}

使用let后:

function func(arr) {
    for (let i = 0; i < arr.length; i++) {
        // i ...
    }
    // 这里访问不到i
}

也就是说,let只能在花括号内部起作用。

const
再来说说const,const代表一个值的常量索引。

const aa = 11;
alert(aa) //11
aa = 22;
alert(aa) //11

但是常量的值在垃圾回收前永远不能改变,所以需要谨慎使用。
还有一条需要注意的就是和其他语言一样,常量的声明必须赋予初值。即使我们想要一个undefined的常量,也需要声明:

const a = undefined;

块级作用域
最后提一下刚才说到的块级作用域。
在之前,javascript是没有块级作用域的,我们都是通过()来模拟块级作用域。

(function(){
 //这里是块级作用域 
})();

但是在ES6中,{}就可以直接代码块级作用域。所以{}内的内容是不可以在{}外访问得到的。
我们可以看看如下代码:

if (true) {
    function foo() {
        document.write( "1" );
    }
}
else {
    function foo() {
        document.write( "2" );
    }
}

foo();      //    在低版本ie上测试2  主流浏览器测试结果1

在我们所认识的javascript里,这段代码的输出结果为2。这个叫做函数声明提升,不仅仅提升了函数名,也提升了函数的定义。如果你基础不扎实的话,可以看看这篇文章:深入理解javascript之IIFE
但是在ES6里,这段代码或抛出ReferenceErroe错误。因为{}的块级作用域,导致外面访问不到foo(),也就是说函数声明和let定义变量一样,都被限制在块级作用域中了。

你可能感兴趣的:(javascript,es6)