JavaScript let与const命令

软件发布|下载排行|最新软件

当前位置:首页IT学院IT技术

JavaScript let与const命令

猪痞恶霸   2022-09-28 我要评论

let命令

基本使用

let是ES6中新增的声明变量的命令,但是和var不同let不可以被重复声明let只在其命令的代码块有效let禁止变量出现变量提升现象,let会通过暂时性死区的方式来避免程序上的错误

  • 代码块:使用{}包括起来的内容

  • 声明变量:分配一个存储空间

  • 不可重复声明let声明过后的变量无法再再次声明,而var可以重复声明

    {
        let a = 10;
        var a = 1; // 'a' has already been declared
    }
    {
        var a = 10
        var a = 1
    }
    console.log(a) // 1
  • 不同代码块可被重复声明:值得注意的是let的不可重复声明是作用在同一代码块中的,后面将会具体解释相关的概念即块级作用域

    {
      let a = 1
      console.log(a)
    }
    {
      let a = 2
      console.log(a)
    }
  • 有效区间的不同let只在其命令的代码块内有效,而var声明的变量可全局有效,下面例子说明两者不同。

    {
        let a = 10;
        var b = 1;
    }
    console.log(a) // a is not defined
    console.log(b) // 1
  • 变量提升:之前使用var声明变量,在声明前调用为undefinedundefined就是我们熟悉的声明但未赋值,这种现象叫做变量提升,但是let禁止了这一行为,使用let所声明的变量一定需要在声明后使用。

    console.log(bar) // Cannot access 'bar' before initialization
    let bar = 2 
  • 变量提升的编译:我们分别来看下变量提升现象在编译后的情况,就能彻底理解变量提升现象出现的原因,所有的声明变量语句在编译后都会将声明语句提到程序的最先级,所以才会出现声明但未赋值的现象。

    // 编译前
    console.log(a)
    var a = '猪痞恶霸'
    // 编译后
    var a 
    console.log(a)
    a = '猪痞恶霸'
  • 暂时性死区:在代码块中使用let声明变量前,该变量不可用,这种现象称为暂时性死区,其实这点和变量提升有些相似,我理解为:let禁止变量提升现象的原因是在声明变量前的代码区域为暂时性死区

    {
        // 暂时性死区
        tmp = 'abc';
        console.log(tmp)
        // 暂时性死区
        let tmp; // 声明tmp,结束暂时性死区
        console.log(tmp) // undefined 声明未赋值
        tmp = '123'
        console.log(tmp) // 123
    }
  • 隐蔽的死区:有些暂时性死区会在我们注意不到的地方,比如

    function bar(x = y, y = 2) { 
        return [x,y]
    }
    bar() // Cannot access 'y' before initialization
    bar(2) // 无错误

    由于x的默认值为y,且y的声明还没开始,所以x = y处于死区中

适用场景

letvar根据其各自不同的特点有着不同的适用场景

  • 计数器的使用:如果我们需要一个用来计数的变量,那么我们就可以使用let来声明。

    var arr = []
    for(let i = 0; i < 10; i++) {
        arr[i] = () => {
            console.log(i)
        } // 利用计数进行操作
    }
    arr[7]() // 7
    for(var i = 0; i < 10; i++) {
        arr[i] = () => {
            console.log(i)
        } // 利用计数进行操作
    }
    arr[7]() // 10

    根据适用varlet的输出结果就能清楚两者的适用场景,而这也凸显了let声明变量的不同之处,即声明的有效区间不同

  • for循环中的父子关系:for循环中有两个作用域,即父作用域与子作用域,设置循环变量的部分为父作用域,循环体内部为子作用域

    for(let i = 0; i < 3; i++) {
        let i = 'abc';
        console.log(i) 
    }
    // abc
    // abc
    // abc

    上面的例子循环打出了三个abc就说明了两个i的作用域不同,如果不在循环体内声明的话将会打印出0,1,2

块级作用域

ES6新增了块级作用域,此前ES5只有全局作用域函数作用域

  • 全局作用域:拥有全局作用域的变量可以在程序的任意位置访问,而window对象的所有属性都具有全局作用域。
  • 函数作用域:又被称为局部作用域,每一个函数中都有一个函数作用域或者嵌套更多的函数作用域,在函数作用域中定义的变量只能在该函数作用域内部使用。

概念

块级作用域的出现其实是由新增声明let产生的

let n = 5
function fn() {
    if(true) {
        let n = 10
    }
    console.log(n)
}
fn() // 5

上面的例子诠释了块级作用域的作用,即外层代码块不受内层代码块的影响,我们在if函数体内声明的n只有在if函数体内可以访问,而fn中访问n不受if内层的声明影响。

存在意义

var tmp = new Date();
function fn() {
    console.log(tmp);
    if(false) {
        var tmp = 'hello world'
    }
}
fn()

如上,存在函数作用域全局作用域,正常情况下fn()函数体内if函数体外是使用外层即var tmp = new Date();但是由于变量提升现象的存在即if函数体内的var tmp = 'hello world'发生了变量提升,即fn()函数体内的编译形式如下,所以输出结果为undefined

function fn() {
    var tmp
    console.log(tmp);
    tmp = 'hello world'
}

块级作用域正是解决了这个问题

let n = 5
function fn() {
    if(true) {
        let n = 10
    }
    console.log(n)
}
fn() // 5

除此之外还可以防止局部作用域变量的泄露到全局当中

let arr = [1,2,3]
for(var i = 0; i < arr.length; i++) {
    console.log(arr[i])
}
{
  console.log(i) // 3
}

如上就造成了变量泄露,i变量被泄露到了全局当中,那么我们使用块级作用域来看一看i is not defined,说明变量未被泄露到全局中。

let arr = [1,2,3]
for(let i = 0; i < arr.length; i++) {
    console.log(arr[i])
}
console.log(i) // i is not defined

const命令

基本使用

const声明的变量无法被再次赋值改变,且声明的时候必须赋值

const name = '猪痞恶霸'
name = 'fzf404' // Assignment to constant variable.
const name // Missing initializer in const declaration
name = '猪痞恶霸'

constlet的特性很像,比如只在其声明的块级作用域内有效,存在暂时性死区

不可被const的情况

javascript中有两种数据类型即:简单数据类型复杂数据类型

简单数据类型:数值,字符串,布尔值

复杂数据类型:数组,对象

引出数据类型的原因正是因为两种数据类型的访问方式不同,简单数据类型的值直接保存变量所指向的内存地址,直接访问就可以拿到值而复杂数据类型的访问是通过变量指向的内存地址,内存地址保存的是另一个指针(引用)

const声明是通过保证变量所指向的那个内存地址不能改动,所有说使用const声明复杂数据类型,会出现数组的元素和对象的属性可以发生改变

const person = {}
person.name = "猪痞恶霸"
console.log(person.name) // 猪痞恶霸

如果我们想要使我们的对象不可以发生改变那么我们可以使用Object.freeze方法,详细使用参考这篇文章:冻结JS对象方法技术详解

Copyright 2022 版权所有 软件发布 访问手机版

声明:所有软件和文章来自软件开发商或者作者 如有异议 请与本站联系 联系我们