详细解析let和const命令

 更新时间:2022年06月24日 14:30:33   作者:​ 陈梵阿   ​  
这篇文章主要介绍了详细解析let和const命令,let和const是es6中新增的命令,一般let用来声明变量而const则用来声明常量,更多相关内容感兴趣的小伙伴可以参考一下

let命令

基本用法

我们都知道let命令是用来声明变量的,类似于var,但是通过let命令声明的变量只在所在代码块内有效。

let a = [];
for (let i = 0;i < 10; i++ ) {
    a[i] = function () {
        console.log(i);
    }
}
a[5](); // 5

如上代码所示,使用的是let声明的i,那么这个变量仅在块级作用域内有效,即只在每轮循环内有效,所以每次循环的i其实都是一个新变量,所以最后输出了5。

如果使用了var去申明i,那么这个i是在全局范围内都有效的,函数数组里的i都会指向同一个i,导出最后输出的是最后一轮循环的i的值。

那就有了一个疑问,使用let声明的i如果每一轮都是一个新变量,那怎么知道上一轮循环的值然后计算出本轮的值?

这是因为JavaScript引擎内部会记住上一轮循环的值,初始化当次循环的i时,会在上一轮循环的基础上计算。

for循环还有一个特别的地方,就是设置循环变量的括号内是一个父作用域,而循环体内是一个单独的子作用域。

特性

不存在变量提升:

不存在变量提升我们应该都知道,在var命令中会发生“变量提升”,就是变量可以在声明之前使用,而值是undefined。这种是比较奇怪的现象,因为他都还没声明怎么就可以使用呢?

所以。let命令改变了这种语法,通过let声明的变量一定要在变量声明后才能用,不然就会报错。

console.log(b) // undefined
console.log(a) // 报错ReferenceError
let a = 2;
var b = 1;

暂时性死区

只要块级作用域内存在Let命令,那么这个let声明的变量就绑定了这个区域,不会受到外部的影响。

var num = 1;
if(true) {
    num = 2; // 报错,ReferenceError
    let num;
}

如上面代码所示,if代码块内想要修改的是if外部的num,但是if内部通过let声明了一个num但为赋值,所以导致了通过let声明的num绑定了这个块级作用域(即if内部这个块级作用域),所以不会受到外部的num影响,所以对num赋值会报错。

ES6明确规定了,如果在区块内存在let和const命令,那么这个区块对这些命令声明的变量从一开始就形成封闭的作用域,只要在声明之前就使用这些变量,就会报做。也称暂时性死区(temporal dead zone,简称TDZ)

当然,这也造成了typeof变得不安全了,因为如果一个变量没有声明就使用typeof不会报错,会返回一个undefined,但是现在不成立了,因为会报错ReferenceError。

function bar(x = y, y = 2) {
    return[x,y] 
}
bar() // 报错

如上代码所示,调用bar函数会报错,因为参数x的默认值等于另一个参数y,但是x在声明的时候y还没有声明,属于死区

总之,只要进入当前作用域,所要使用的变量就已经存在,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。

其实let和const是存在变量提升的,但是由于暂时性死区的关系,变量已经存在了,但是不可获取,要等到声明变量的时候才可以获取和使用。

不允许重复声明

let不允许在校内共同作用域内重复声明同一个变量,这个就不用说了大家都知道。

let a = 1;
let a = 2; // 报错

const

我们都知道const声明一个只读的常量。修改这个值就会报错。但是实际上保证的不是变量的值不能改动,而是变量指向的那个内存地址不能改动。

对于简单数据类型来说,值就是保存在变量指向的内存地址中,因此等同于常量。

而对于复合类型的数据,变量指向的内存地址保存的是一个指针,const只保证指针是固定,不保证内部的结构是不是可变的。

    // 给对象添加一个属性
    const foo = {}
    foo.name = 123
    console.log(foo.name) // 123
    // 将foo指向另一个对象,就会报错
    foo = {} // 报错。

如果想要将对象冻结,可以使用Object.freeze

const foo = Object.freeze({});

特性

  • 只在声明所在的块级作用域内有效。
  • const声明的常量不会提升,同样存在暂时性死区,只能在声明后使用。
  • 不可重复声明。

补充——块级作用域

函数能不能在块级作用域中声明呢?

ES5中是规定函数只能在顶级作用域和函数作用域之中声明,不能在块级作用域声明。

ES6中引入了块级作用域,明确允许在块级作用域之中声明函数。而且。函数声明的语句的行为类似于let,在块级作用域之外不可引用。

function f() {
    console.log('I am outside!')
}
(function() {
    if(false) {
        function f() {
            console.log('I am inside')
        }
    }
}
f();
}())

上面的代码,在es5中运行时会得到I am inside!,因为if内部的f函数会被提升到函数头部。

但是在ES6环境则会报错,为什么呢?

因为游览器的实现有自己的方式:

  • 允许在块级作用域内声明函数
  • 函数声明类似于var,会提升到全局作用域或函数作用域的头部
  • 函数声明还会提升到所在的块级作用域的头部

所以上述代码实际在ES6的游览器中会生成这样的代码:

  function f() {
    console.log("I am outside!");
  }
  (function () {
    var f = undefined;
    if (false) {
      function f() {
        console.log("I am inside");
      }
    }
  })();

因此,应该避免在块级作用域内声明函数,如果确定需要写成函数表达式的形式,而不是函数声明语句。

到此这篇关于详细解析let和const命令的文章就介绍到这了,更多相关let和const内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • JavaScript生成的动态下雨背景效果实现方法

    JavaScript生成的动态下雨背景效果实现方法

    这篇文章主要介绍了JavaScript生成的动态下雨背景效果实现方法,通过自定义函数实现动态背景效果,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-02-02
  • 基于IE下ul li 互相嵌套时的bug,排查,解决过程以及心得介绍

    基于IE下ul li 互相嵌套时的bug,排查,解决过程以及心得介绍

    昨天到今天上午都在查一个IE的bug,情形如下:通过异步请求获取json数据,然后拼接成html代码,最后使用innerHTML类似方法插入到文档流中。在chrome下和IE8\9下均表现正常。结果已进入IE7,浏览器就崩溃,更别提IE6了,也是一副死给你看的样子。于是我就把这个bug定位于IE6\7,其实这时候我已经陷入了这个固定思维模式中,浪费了不少时间
    2013-05-05
  • JavaScript实现类似拉勾网的鼠标移入移出效果

    JavaScript实现类似拉勾网的鼠标移入移出效果

    其实也是个偶然的机会让我想去研究一下这个效果。主要是由于有个群里的人发了个讲解这个效果的链接,当时也没怎么在意,然后过两天,突然就想起这件事,便去拉勾网一看,效果不错啊,所以就自己研究起来,现在将过程分享给大家,有需要的可以参考借鉴。
    2016-10-10
  • 教你javascript如何获取对象的key和value

    教你javascript如何获取对象的key和value

    获取对象所有key的方法,需要使用 Object.keys(obj) 方法,Object.keys(obj)方返回一个数组,这个数组包含obj对象中的所有key,这篇文章主要介绍了javascript如何获取对象的key和value,需要的朋友可以参考下
    2022-12-12
  • JavaScript无提示关闭窗口(兼容IE/Firefox/Chrome)

    JavaScript无提示关闭窗口(兼容IE/Firefox/Chrome)

    JavaScript无提示关闭当前页面窗口,兼容IE/Firefox/Chrome (Close the current page window without confirm by JavaScript, support all browsers)
    2008-11-11
  • 25个让你眼前一亮的JavaScript代码技巧分享

    25个让你眼前一亮的JavaScript代码技巧分享

    学习强大的JavaScript一行代码,能够节省你的时间和代码量,所以本文为大家整理了25个JavaScript实用代码技巧,感兴趣的小伙伴可以了解一下
    2023-07-07
  • 整理Javascript数组学习笔记

    整理Javascript数组学习笔记

    整理Javascript数组学习笔记,之前一系列的文章是跟我学习Javascript,本文就是进一步学习javascript数组,希望大家继续关注
    2015-11-11
  • 如何防止JavaScript中的正则表达式回溯

    如何防止JavaScript中的正则表达式回溯

    某些正则表达式模式可能容易受到回溯的影响,这可能会导致超线性运行时,并可能导致DoS攻击,本文就来介绍一下如何防止JavaScript中的正则表达式回溯,感兴趣的可以了解一下
    2023-08-08
  • 解析如何利用iframe标签以及js制作时钟

    解析如何利用iframe标签以及js制作时钟

    本文对如何利用iframe标签以及js制作时钟进行了全面解析,分步说明,条理清晰,感兴趣的朋友可以看下
    2016-12-12
  • 页面中body onload 和 window.onload 冲突的问题的解决

    页面中body onload 和 window.onload 冲突的问题的解决

    关于页面中body onload 和 window.onload 冲突的问题的解决
    2009-07-07

最新评论