let、const块级声明与块级作用域绑定

let、const块级声明与块级作用域绑定

let、const与块级作用域

在ES6之前JS的作用域有三种,它们分别为:
全局作用域
函数作用域
Eval作用域
为了让JavaScript更加灵活,ES6版本新引入了C系语言的“块级作用域”这一概念,伴随这一概念诞生的是两种新的变量声明方法,他们依赖于块级作用域而存在(块级作用域的存在也依赖于let和const),下文细说。

一、什么是块级作用域?

块级作用域(词法作用域):存在于函数内和成对的大括号内,是函数或大括号{}圈定的一块代码块里形成的一个单独的作用域。实际上这么说并不严谨,因为在ES6以前这种大括号就存在了,函数也是很早就有,但那时候还并没有块级作用域这一概念,所以

||仅仅在大括号中有let或者const这两个 用来声明块级标识符的关键字 声明了东西的时候,这个大括号内才是一片块级作用域||

“块级声明”就是在这块被圈起来的作用域里使用let或者const声明变量(也是要声明出来才能让此处成为块级作用域),执行流一旦走出let块级变量所在的块级作用域,这个块级变量会被立刻销毁返回undefined(作用域外无法访问)。

二、let声明

let的使用方法与var相同,仅将var替换为let即可,其余无需改动,在函数内或一对大括号内使用,将在函数内部/大括号内形成一个块级作用域。由于其不会像var声明变量一样被提升优先解析,一般将使用let进行块级声明的代码放在代码块的顶部,以使整个代码块都能使用其声明物。其可以用于声明全局变量,但仅能在script域中生效。
但若是欲使用let来重新声明变量以完成对变量的更新,不可使用var的直接覆盖法。
let更新变量方法:当待更新的变量存在于母作用域,而用于更新母作用域中的变量的let存在于子作用域时,可以直接用let来覆写母作用域中的同名变量,而子作用域中的let覆写的这个变量也不会仅仅是只在子作用域中生效,其会在全局上改变这个变量的值。

在进行for循环语句时,使用let来声明变量i(循环的key)可以达到在for内形成块级作用域的目的,变量i将不能在循环外被访问。let形成的块级作用域也可以解决在for循环内放函数导致变量共用产生的问题。
在for( in )和for( of )这两种循环形式中,let通过在每次循环时创建新的绑定而不是修改绑定来保证自身的运行,同时使循环体依照循环次数能够访问到相应的值。

三、const声明

const声明的仅能为常量,出于与变量的区别,const声明出的常量,值不能像变量一样改变,所以必须为每个声明出的常量进行初始化。所谓初始化就是为它赋一个值,这个值就是初始化后的结果,若是仅仅使用const声明一个常量而不为其赋值(初始化),则会抛出语法错误。
const同于let,也是一个块级标识符,那么它声明的常量也是仅仅在当前这个代码块(块级作用域)内部有效。由于其不会像var声明变量一样被提升优先解析,一般将使用const进行块级声明的代码放在代码块的顶部,以使整个代码块都能使用其声明物。
若是欲使用const来重新声明常量以完成对常量的更新,也不可使用var的直接覆盖法。
const更新常量方法:其与let不同,无论与严格/非严格模式下,其声明的常量(除对象外)都不能被再赋值,其并非不支持修改值,而是不支持修改绑定,导致看起来是不能修改值。但若是用其来定义一个对象,我们就可以修改对象的属性值,其值可以修改这条便体现出来。
const定义的对象的更改:

    const demo = {
       属性:"值1"
    };
     //以下是正确修改
    demo.属性 = "值2"
    
    //以下是错误修改
    demo = {
    属性:"值2"
    };

上面的例子里const绑定的是对象demo,const不支持修改绑定,故最后一种修改了绑定的方法抛出了语法错误,而第一种修改方法仅仅改变了值,这是受到const支持的行为,没有抛出错误。

const可以在循环语句中使用,但是其在不同的循环语句中会表现出不同的行为。在for循环中使用const来定义(初始化)i(即循环的key),那么就会抛出错误,执行“i++”这条语句时,const发现它试图修改常量,就抛出了错误。因此在循环语句中,const能声明的变量仅仅能是那些在后续的循环中不会被循环语句修改的变量。
在for( in )和for( of )这两种循环形式中,const通过在每次循环时创建新的绑定而不是修改绑定来保证自身的运行,同时使循环体依照循环次数能够访问到相应的值。

四、let与const的缺点

1.let

不能重声明,无论用何种方法(包括const),在一作用域内声明了一个变量后,不能在该作用域内再次使用let来声明一个同名的变量来对该变量进行更新,若是直接试图用let来更新同名变量会抛出语法错误。
解析JavaScript代码时不能自动提升,需要写在最上面。
需要注意作用域。

2.const

不能重声明,无论用何种方法(包括let),在一作用域内声明了一个变量后,不能在该作用域内再次使用const来声明一个同名的变量来对该变量进行更新,若是直接试图用const来更新同名变量会抛出语法错误。
解析JavaScript代码时不能自动提升,需要写在最上面。
写到不同的循环里会表现出不同的行为,在for循环中使用可能会引发错误。
需要注意作用域。

五、体现于全局作用域处相比var的优点

当使用var来声明全局变量时,这个全局变量会被全局对象作为一个新属性添加到全局属性里,若是全局属性里本就有这次要添加进去的新属性,这次添加会将原本的属性覆写,为后面的使用造成麻烦。
但如果使用let或者const来声明全局变量,会在全局作用域下创建一个新的绑定,但是这个绑定不会全局对象添加为一个全局属性,如果原有全局属性和这次声明的全局变量发生名上的冲突,原有属性将不会被覆写,两者会共同存在,但是这个“共同存在”仅仅局限于名字上,声明一个全局变量为demo,并且假设原本有一个全局属性window.demo,那么:

const demo = "HelloWorld";
console.log(demo);//输出HelloWorld
console.log("demo" in window);//输出false

由此可见使用let和const声明变量可以避免对全局作用域产生破坏。

总结

在声明大多数值时使用const,因为大多数值在声明(初始化)后便不需要再改变,预料之外的变量改变通常会成为错误的源头,而在处理少数需要跟随情况变化的值时使用let。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值