Es6入门之块级作用域

Es6入门之块级作用域

块级作用域

首先有学习过javascript的童鞋应该都清楚,js之中不像java这些静态语言存在纯天然的块级作用域。js的作用域是以函数来区分

  • 最常见的例子
    for(var i = 0;i<10;i++){
        //code here...
    }
    console.log(i);//10

对的,没错,上面输出的i是10;这个会让从有块级作用作用域语言转过来的人一脸懵逼!究其原因就是因为js中的作用域是以函数来区分的,而非{}符号

  • 函数作用域例子
    var fn = function (){
        for(var i = 0;i<10;i++){
            //code here...
        }
    }

    console.log(i);
    //ReferenceError: i is not defined

以上例子才是js作用域的真正体现!以函数为界限,js由內至外形成一个作用域链,外部作用域不可以访问内部作用域,内部作用则可以访问外部作用域。以下图片可以简单说明作用域链是啥东东:

作用域链示意图


谢天谢地:) ECMAscript 6标准的发布,给我们javascript带来块级作用域,撒花~

块级作用域之let

let关键字的出现,就是js实现块级作用域之时;另外一个const关键字,两者稍稍有些区别,下面再赘述

  • 下面使用let实现块级作用域的例子
    for(let i = 0;i<10;i++){
            //code here...
    }
    // 由于使用了let关键字,所以i变量只在for循环里面有效,形成了一个块级作用域,外部作用域再反问i变量则报错
    console.log(i);
    // ReferenceError: i is not defined

块级作用域之const

const关键字与let关键字的不同点在于前者用于定义常量!使用过java语言的童鞋应该知道final关键字就是用来定义常量的,常量是不可修改的变量

  • 举个栗子

java写法

final int PI = 3.14;

Es6写法

const PI = 3.14;
// 因为const定义的变量是常量,不可修改,因此执行到这句将会发生错误
PI = 3.1415926;
//Uncaught TypeError: Assignment to constant variable.

其实以前Es6标准还没有发布,各位前辈是这样实现js的块级作用域的

// 其实也就是使用函数的特性
// 再利用IIFE(Immediately-invoked function expression,中文就是立即执行函数)的特性
(function (){
    // code here...
})()

为什么需要块级作用域

块级作用域,这使js编程更符合常理,解决了那些对js不熟悉的使用者,分分钟写出不自知的WTF的bug

  • 经典场景:闭包(不懂的童鞋可以自行搜索,由于篇幅原因,不在这里展开赘述)
    // 假设li的数量有3个
    var aLis = document.querySelectorAll("#list li");
    for(var i = 0; i < aLis.length; i++){
        aLis[i].onclick = function (){
            console.log(i);//一直输出3
        }
    }

哈哈,傻眼了吧,怎么输出的不是0,1,2?这就是因为特么的有个闭包啊!以前我们的解决方案一般是这样:

    // 假设li的数量有3个
    var aLis = document.querySelectorAll("#list li");
    for(var i = 0; i < aLis.length; i++){
        aList[i].index = i;
        aLis[i].onclick = function (){
            console.log(this.index);//0,1,2
        }
    }

let的解决方案:

    // 假设li的数量有3个
    var aLis = document.querySelectorAll("#list li");
    for(let i = 0; i < aLis.length; i++){
        aLis[i].onclick = function (){
            console.log(i);//0,1,2
        }
    }

高下立见,明显有了let我们实现更加优雅了,而不用使用那些hack方法

let和const使用的注意事项

1.不像var那样会发生“变量提升”
2.同一个块级作用域不允许重复声明同一个名称的变量
3.const用于声明常量,不可更改且必须立即初始化
4.letconstclass等关键字声明的变量将不同于varfunction,不再默认附属于全局对象的属性
谨记,注意TDZ(Temporal Dead Zone)–块级作用域引起的暂时性死区

  • 不存在变量提升
    console.log(i);
    //Uncaught ReferenceError: i is not defined
    let i = 10;

    console.log(j);//undefined
    var j = 10;
  • 不允许重复声明同一个变量
    let i = 10;
    let i = 5;//Uncaught SyntaxError: Identifier 'i' has already been declared
  • const声明常量必须初始化
    const PI;//Uncaught SyntaxError: Missing initializer in const declaration
  • let/const/class关键字声明的变量不再附着于全局变量
    // 假设是在客户端场景下
    var width = 100;
    let height = 100;
    console.log(window.width);//100
    console.log(window.height);//undefined
  • TDZ,暂时性死区

暂时性死区是因为使用了let/const等关键字,在那块块级作用域里面就会对声明的变量进行锁定,然后如果在let/const声明之前使用该该变量则会报错

  • 对方不想和你说话,并向你扔了个栗子
    // TDZ栗子1
    var temp = 'hello';
    if(true){
        // TDZ(temple died zone)开始
        try{
            temp = "es6";//报错,变量temp is not defined
        }catch(e){
            console.log(e);
        }
        let temp;
        // TDZ(temple died zone)结束
        console.log(temp);//undefined
    }
    // TDZ栗子2:这里是由于x的默认值是y,而y又还没声明导致的暂时性死区问题
    try{
        (function (x=y,y=2){
            console.log([x,y])
        })()
    }catch(e){
        console.log(e);
    }

参考文献

Es6标准入门(第二版)——阮一峰 著->传送门
javascript高级程序设计(第三版)——[美]Nichilas C.Zakas 著

更多原创文章请关注博主个人独立博客——zifengBlog

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值