[前端] JavaScript中let与const命令使用

1987 0
黑夜隐士 2022-10-21 15:46:07 | 显示全部楼层 |阅读模式
目录

    let命令
      基本使用适用场景
    块级作用域
      概念存在意义
    const命令
      基本使用不可被const的情况



let命令



基本使用

let是ES6中新增的声明变量的命令,但是和var不同,let不可以被重复声明,let只在其命令的代码块有效,let禁止变量出现变量提升现象,let会通过暂时性死区的方式来避免程序上的错误
    代码块:使用{}包括起来的内容
    声明变量:分配一个存储空间
  • 不可重复声明:let声明过后的变量无法再再次声明,而var可以重复声明
    1. {
    2.     let a = 10;
    3.     var a = 1; // 'a' has already been declared
    4. }
    复制代码
    1. {
    2.     var a = 10
    3.     var a = 1
    4. }
    5. console.log(a) // 1
    复制代码
  • <strong>不同代码块可被重复声明:值得注意的是let的不可重复声明是作用在同一代码块中的,后面将会具体解释相关的概念即块级作用域
    1. {
    2.   let a = 1
    3.   console.log(a)
    4. }
    5. {
    6.   let a = 2
    7.   console.log(a)
    8. }
    复制代码


  • 有效区间的不同:let只在其命令的代码块内有效,而var声明的变量可全局有效,下面例子说明两者不同。
    1. {
    2.     let a = 10;
    3.     var b = 1;
    4. }
    5. console.log(a) // a is not defined
    6. console.log(b) // 1
    复制代码
  • 变量提升:之前使用var声明变量,在声明前调用为undefined,undefined就是我们熟悉的声明但未赋值,这种现象叫做变量提升,但是let禁止了这一行为,使用let所声明的变量一定需要在声明后使用。
    1. console.log(bar) // Cannot access 'bar' before initialization
    2. let bar = 2
    复制代码
  • 变量提升的编译:我们分别来看下变量提升现象在编译后的情况,就能彻底理解变量提升现象出现的原因,所有的声明变量语句在编译后都会将声明语句提到程序的最先级,所以才会出现声明但未赋值的现象。
    1. // 编译前
    2. console.log(a)
    3. var a = '猪痞恶霸'
    4. // 编译后
    5. var a
    6. console.log(a)
    7. a = '猪痞恶霸'
    复制代码
  • 暂时性死区:在代码块中使用let声明变量前,该变量不可用,这种现象称为暂时性死区,其实这点和变量提升有些相似,我理解为:let禁止变量提升现象的原因是在声明变量前的代码区域为暂时性死区
    1. {
    2.     // 暂时性死区
    3.     tmp = 'abc';
    4.     console.log(tmp)
    5.     // 暂时性死区
    6.     let tmp; // 声明tmp,结束暂时性死区
    7.     console.log(tmp) // undefined 声明未赋值
    8.     tmp = '123'
    9.     console.log(tmp) // 123
    10. }
    复制代码
  • 隐蔽的死区:有些暂时性死区会在我们注意不到的地方,比如
    1. function bar(x = y, y = 2) {
    2.     return [x,y]
    3. }
    4. bar() // Cannot access 'y' before initialization
    5. bar(2) // 无错误
    复制代码
    由于x的默认值为y,且y的声明还没开始,所以x = y处于死区中

适用场景

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

  • 计数器的使用:如果我们需要一个用来计数的变量,那么我们就可以使用let来声明。
    1. var arr = []
    2. for(let i = 0; i < 10; i++) {
    3.     arr[i] = () => {
    4.         console.log(i)
    5.     } // 利用计数进行操作
    6. }
    7. arr[7]() // 7
    复制代码
    1. for(var i = 0; i < 10; i++) {
    2.     arr[i] = () => {
    3.         console.log(i)
    4.     } // 利用计数进行操作
    5. }
    6. arr[7]() // 10
    复制代码
    根据适用var和let的输出结果就能清楚两者的适用场景,而这也凸显了let声明变量的不同之处,即声明的有效区间不同
  • for循环中的父子关系:for循环中有两个作用域,即父作用域与子作用域,设置循环变量的部分为父作用域,循环体内部为子作用域
    1. for(let i = 0; i < 3; i++) {
    2.     let i = 'abc';
    3.     console.log(i)
    4. }
    5. // abc
    6. // abc
    7. // abc
    复制代码
    上面的例子循环打出了三个abc就说明了两个i的作用域不同,如果不在循环体内声明的话将会打印出0,1,2

块级作用域

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

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

概念

块级作用域的出现其实是由新增声明let产生的
  1. let n = 5
  2. function fn() {
  3.     if(true) {
  4.         let n = 10
  5.     }
  6.     console.log(n)
  7. }
  8. fn() // 5
复制代码
上面的例子诠释了块级作用域的作用,即外层代码块不受内层代码块的影响,我们在if函数体内声明的n只有在if函数体内可以访问,而fn中访问n不受if内层的声明影响。

存在意义
  1. var tmp = new Date();
  2. function fn() {
  3.     console.log(tmp);
  4.     if(false) {
  5.         var tmp = 'hello world'
  6.     }
  7. }
  8. fn()
复制代码
如上,存在函数作用域全局作用域,正常情况下fn()函数体内if函数体外是使用外层即var tmp = new Date();但是由于变量提升现象的存在即if函数体内的var tmp = 'hello world'发生了变量提升,即fn()函数体内的编译形式如下,所以输出结果为undefined。
  1. function fn() {
  2.     var tmp
  3.     console.log(tmp);
  4.     tmp = 'hello world'
  5. }
复制代码
块级作用域正是解决了这个问题
  1. let n = 5
  2. function fn() {
  3.     if(true) {
  4.         let n = 10
  5.     }
  6.     console.log(n)
  7. }
  8. fn() // 5
复制代码
除此之外还可以防止局部作用域变量的泄露到全局当中
  1. let arr = [1,2,3]
  2. for(var i = 0; i < arr.length; i++) {
  3.     console.log(arr[i])
  4. }
  5. {
  6.   console.log(i) // 3
  7. }
复制代码
如上就造成了变量泄露,i变量被泄露到了全局当中,那么我们使用块级作用域来看一看i is not defined,说明变量未被泄露到全局中。
  1. let arr = [1,2,3]
  2. for(let i = 0; i < arr.length; i++) {
  3.     console.log(arr[i])
  4. }
  5. console.log(i) // i is not defined
复制代码
const命令

基本使用

const声明的变量无法被再次赋值改变,且声明的时候必须赋值
  1. const name = '猪痞恶霸'
  2. name = 'fzf404' // Assignment to constant variable.
复制代码
  1. const name // Missing initializer in const declaration
  2. name = '猪痞恶霸'
复制代码
const与let的特性很像,比如只在其声明的块级作用域内有效,存在暂时性死区

不可被const的情况

javascript中有两种数据类型即:简单数据类型复杂数据类型
简单数据类型:数值,字符串,布尔值
复杂数据类型:数组,对象
引出数据类型的原因正是因为两种数据类型的访问方式不同,简单数据类型的值直接保存变量所指向的内存地址,直接访问就可以拿到值而复杂数据类型的访问是通过变量指向的内存地址,内存地址保存的是另一个指针(引用)
const声明是通过保证变量所指向的那个内存地址不能改动,所有说使用const声明复杂数据类型,会出现数组的元素和对象的属性可以发生改变
  1. const person = {}
  2. person.name = "猪痞恶霸"
  3. console.log(person.name) // 猪痞恶霸
复制代码
如果我们想要使我们的对象不可以发生改变那么我们可以使用Object.freeze方法,详细使用参考这篇文章:冻结JS对象方法技术详解
到此这篇关于JavaScript中let与const命令使用的文章就介绍到这了,更多相关JavaScript let与const命令内容请搜索中国红客联盟以前的文章或继续浏览下面的相关文章希望大家以后多多支持中国红客联盟!
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

中国红客联盟公众号

联系站长QQ:5520533

admin@chnhonker.com
Copyright © 2001-2025 Discuz Team. Powered by Discuz! X3.5 ( 粤ICP备13060014号 )|天天打卡 本站已运行