zoukankan      html  css  js  c++  java
  • 《关于ES6的学习》

    var

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

    也就是说,如果在函数内部声明的变量,都会被提升到该函数开头,而在全局声明的变量,就会提升到全局作用域的顶部。

    function test() {
        console.log('1: ', a) //undefined
        if (false) {
          var a = 1
        }
        console.log('3: ', a) //undefined
    }
    
    test()

    实际执行时,上面的代码中的变量a会提升到函数顶部声明,即使if语句的条件是false,也一样不影响a变量提升。

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

    在函数嵌套函数的场景下,变量只会提升到最近的一个函数顶部,而不会。

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

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

    //a没有声明的情况
    a 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"
    

    我们试试重新声明type,看看会报什么错:

    
    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和let的异同点

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

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

    临时死区(TDZ)

    上面我们也提到了TDZ的场景,那么,有什么用呢?答案就是没什么用。

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

    
    if (true) {
      //这块区域是TDZ
      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无法污染外部函数

    在全局作用域声明

    如果在全局作用域使用let或者const声明,当声明的变量本身就是全局属性,比如closed。只会覆盖该全局变量,而不会替换它。

    window.closed = false
    let closed = true
    
    closed // true
    window.closed // false
    

    最佳实践

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

  • 相关阅读:
    XCode5中新建工程后强制使用了ARC,如何去掉?
    面向对象程序的设计原则--Head First 设计模式笔记
    ios控件自定义指引
    iOS UITableViewDelegate && UITableViewDataSource 执行顺序
    awakeFromNib方法和viewDidLoad方法区别
    ios 视图的旋转及应用
    线段树模板 (刘汝佳)
    poj 3468
    hdu 2829(四边形优化 && 枚举最后一个放炸弹的地方)
    poj 3517(约瑟夫环问题)
  • 原文地址:https://www.cnblogs.com/gopark/p/8157283.html
Copyright © 2011-2022 走看看