资讯专栏INFORMATION COLUMN

深入理解ES6笔记(一)块级作用域绑定

马忠志 / 2576人阅读

摘要:和都能够声明块级作用域,用法和是类似的,的特点是不会变量提升,而是被锁在当前块中。声明常量,一旦声明,不可更改,而且常量必须初始化赋值。临时死区临时死区的意思是在当前作用域的块内,在声明变量前的区域叫做临时死区。

主要知识点有:var变量提升、let声明、const声明、let和const的比较、块级绑定的应用场景

《深入理解ES6》笔记 目录

var

JavaScript中,我们通常说的作用域是函数作用域,使用var声明的变量,无论是在代码的哪个地方声明的,都会提升到当前作用域的最顶部,这种行为叫做变量提升(Hoisting)

function test() {
    var a
    //a声明没有赋值
    console.log("1: ", a) //undefined
    if (false) {
      a = 1
    }
    //a声明没有赋值
    console.log("3: ", a) //undefined
}

test()

如果a没有声明,那么就会报错,没有声明和声明后没有赋值是不一样的,这点一定要区分开,有助于我们找bug。

//b提升到函数a顶部,但不会提升到函数test。
function test() {
    function a() {
      if (false) {
        var b = 2
      }
    }
    console.log("b: ", b)
}

test() //b is not defined
let

let和const都能够声明块级作用域,用法和var是类似的,let的特点是不会变量提升,而是被锁在当前块中。

function test() {
    if(true) {
      console.log(a)//TDZ,俗称临时死区,用来描述变量不提升的现象
      let a = 1
    }
}
test()  // a is not defined

function test() {
    if(true) {
      let a = 1
    }
    console.log(a)
}    
test() // a is not defined

唯一正确的使用方法:先声明,再访问

function test() {
    if(true) {
      let a = 1
      console.log(a)
    }
}
test() // 1
const

声明常量,一旦声明,不可更改,而且常量必须初始化赋值。

const type = "ACTION"

重新赋值会报错

const type = "ACTION"
type = 1
console.log(type) //"type" is read-only

const type = "ACTION"
let type = 1
console.log(type) //Duplicate declaration "type"

const虽然是常量,不允许修改默认赋值,但如果定义的是对象Object,那么可以修改对象内部的属性值。

const type = {
  a: 1
}
type.a = 2 //没有直接修改type的值,而是修改type.a的属性值,这是允许的。
console.log(type) // {a: 2}

const声明不允许修改绑定,但允许修改绑定的值

const和let的异同点:

相同点:const和let都是在当前块内有效,执行到块外会被销毁,也不存在变量提升(TDZ),不能重复声明。

不同点:const不能再赋值,let声明的变量可以重复赋值。

临时死区(TDZ)

临时死区的意思是在当前作用域的块内,在声明变量前的区域叫做临时死区。

if (true) {
  //这块区域是TDZ,访问a会报错
  let a = 1
}

访问TDZ中的变量会触发运行时错误
但下面这种不会报错

console.log(typeof a) //undefined,因为此时a不在TDZ中
if (true) {
  //这块区域是TDZ,访问a会报错
  let a = 1
}
块级作用域的使用场景

除了上面提到的常用声明方式,我们还可以在循环中使用,最出名的一道面试题:循环中定时器闭包的考题

在for循环中使用var声明的循环变量,会跳出循环体污染当前的函数。

for(var i = 0; i < 5; i++) {
  setTimeout(() => {
    console.log(i) //5, 5, 5, 5, 5
  }, 0)
}
console.log(i) //5 i跳出循环体污染外部函数

//将var改成let之后
for(let i = 0; i < 5; i++) {
  setTimeout(() => {
    console.log(i) // 0,1,2,3,4
  }, 0)
}
console.log(i)//i is not defined i无法污染外部函数

循环内const声明
在普通的for循环中使用const变量,由于const变量不可修改,因此会报错。而在for-in或者for-of循环中可以使用const变量。
因为循环为每次迭代创建了一个新的变量绑定,而不是试图去修改已绑定的变量的值

let arr = [1,2,3,4];
 for(const item of arr){
     console.log(item); //输出1,2,3,4
 }
全局块作用域绑定

用var作用域全局作用域时声明的全局变量会覆盖一个已经存在的全局属性:

var reg = "hello";
console.log(window.reg) //"hello"

而如果在全局作用域使用let或者const声明,当声明的变量本身就是全局属性,比如closed。会创建一个新的绑定,但不会添加全局属性;就是说,用let或const不能覆盖全局变量,只能遮蔽它;

window.closed = false
let closed = true

closed // true
window.closed // false
最佳实践

在实际开发中,我们选择使用var、let还是const,取决于我们的变量是不是需要更新,通常我们希望变量保证不被恶意修改,而使用大量的const,声明一个对象的时候,也推荐使用const,当你需要修改声明的变量值时,使用let,var能用的场景都可以使用let替代。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/96866.html

相关文章

  • 深入理解ES6 () 块级绑定

    摘要:声明声明的语法与的语法一致。总结文章都是以深入理解读书笔记形式,大部分引用书中的定义,加上作者的理解,样例也做了调整,所有样例都可以放到里运行亲自尝试。 1.变量提升 使用 var 关键字声明的变量,无论其实际声明位置在何处,都会被视为声明于所在函数的 顶部(如果声明不在任意函数内,则视为在全局作用域的顶部)。这句话从字面上不难理解。 但是他是怎样一个过程,为什么会这样。当你代...

    KunMinX 评论0 收藏0
  • 深入理解ES6笔记——块级作用绑定(1)

    摘要:没有声明的情况和都能够声明块级作用域,用法和是类似的,的特点是不会变量提升,而是被锁在当前块中。声明常量,一旦声明,不可更改,而且常量必须初始化赋值。临时死区的意思是在当前作用域的块内,在声明变量前的区域叫做临时死区。 本章涉及3个知识点,var、let、const,现在让我们了解3个关键字的特性和使用方法。 var JavaScript中,我们通常说的作用域是函数作用域,使用var声...

    2bdenny 评论0 收藏0
  • 深入理解ES6笔记——函数(3)

    摘要:错误的写法错误的写法中的构造函数新增了支持默认参数和不定参数。箭头函数的简单理解箭头函数的左边表示输入的参数,右边表示输出的结果。但是有了尾调用优化之后,递归函数的性能有了提升。 作为前端切图仔,越发觉得自己离不开函数了。 说到JavaScript函数,脑子里都是匿名函数、普通函数、闭包函数、构造函数......然后还能说出一大堆函数的概念。如果你达到这个水平,那么函数对你来说没有难度...

    DoINsiSt 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<