博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
ES6学习之 -- let和const命令
阅读量:6622 次
发布时间:2019-06-25

本文共 3833 字,大约阅读时间需要 12 分钟。

  1. let命令

    用来声明变量,它的用法类似var,但是let命令声明的变量只在所在的代码块中有效。

    {    var a = 1;    let b = 2;}console.log(a); // 1console.log(b); // b is not defined b未定义

    这就说明let定义的变量只在对应的代码块中有效。

    同样的下面是个for循环

    for(let i = 0; i < 5; i++){    // ...}console.log(i);// i is not defined i未定义

    i只在循环体内有效。

    阮一峰老师的文章中有一个例子我们看一下并且分析一下

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

    老师给我们的分析是这样子的:

    上面代码中,变量i是let声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是6。你可能会问,如果每一轮循环的变量i都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。
    如果还不理解的话我们可以再看一个例子:
    var a = [];for (let i = 0; i < 10; i++) {  let val = i;  a[i] = function () {    console.log(val);  };}a[6](); // 6

    这时候你就会理解原因了,就相当于for循环中的执行体,每次的执行都位于一个单独的代码块中。这个val是我们显示定义的一个副本,当我们执行a[6]的时候,他会找到a[6]保存的函数的执行环境下去找这个val,数组a中的每个元素都位于一个单独的代码块中互不影响。那么我们可以得出一个结论:js引擎会为我们for循环中每次循环的代码块保存一个副本。

    Nicholas C. Zakas《深入理解ES6》中也有相关解释。
    不存在变量提升

    console.log(a);// undefinedconsole.log(b);// b is not definedvar a = 1;let b = 2;

    暂时性死区

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

    var temp = 'hello';if(true){    console.log(temp);// temp is not defined    let temp;}原因就是let绑定了块级作用域并且let定义的变量不会提升,就是这个地盘跟我同名的都得死。隐蔽的死区function test(x = y, y = 2) {    return [x, y];}test();// 报错

    原因是:当执行test()的时候会先将y的值赋给x作为初始值,但此时y不存在,所以报错。

    function test(x = 2, y = x) {    return [x, y];}test();// [2, 2]

    这样就没问题了。

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

    不允许重复声明

    let不允许在同一作用域声明两个相同的变量。

    let a;var a;//报错  a已经被声明了
    function fun(params) {    let params;}func();//报错  params已经被声明了function test(params) {    {//内部代码块        let params;    }}test();//正常执行  执行函数内部的代码块被其中的那个变量占用了而已

    块级作用域

    先看一下es5,es5只有全局作用域和函数作用域。

    var name = 'Jason';function test() {    console.log(name);    if(false) {        var name = 'Nico';    }}==>相当于var name = 'Jason';function test() {    var name;//变量提升    console.log(name);    if(false) {        name = 'Nico';    }}所以执行test()会打印undefined

    还有就是for循环的时候i的定义被提前

    for(var i = 0; i < 3; i++) {    console.log(i);}console.log(i);依次打印0 1 2 3

    原因是i定义被提前,如下:

    var i;for(i = 0; i < 3; i++) {    console.log(i);}console.log(i);

    es6出现了块级作用域

    function test() {    let n = 0;    if(true) {        let n = 1;    }    console.log(n);}test();// 0

    外层的块级作用域不受内层的控制。

    {    {        let a = 1;    }    console.log(a);//报错 a未被定义}

    外层作用域无法访问内层作用域定义的变量

    {    let a = 0;    {        let a = 1;    }}

    内层作用域可以命名外层已经命名的变量。

    值得提醒的是函数在块级作用域中的声明

    function test() {    console.log('outside');}(function() {    if(false) {        function test() {            console.log('inside');        }    }    console.log(test());})();

    ES5会打印inside字符串,ES6却会报test is not a function的错。

    是不是很诧异,为什么ES6没有打印outside呢?

    原因是:ES6中允许块级作用域中声明函数,但是函数声明会类似于var提升到全局作用域或者函数作用域头部,同时函数声明会提升到块级作用域头部,所以上面的代码就相当于
    function test() {    console.log('outside');}(function() {    var test = undefined;    if(false) {        function test() {            console.log('inside');        }    }    console.log(test());})();所以才会报test is not a function的错误。

    所以尽量避免块级作用域中声明函数,如果有必要的话可以使用函数表达式。

    function test() {    console.log('outside');}(function() {    if(false) {        let test = function() {            console.log('inside');        }    }    console.log(test());// outside})();
  2. const命令

    用于定义常量,一旦定义必须立刻初始化不然报错,定义后无法改变值,改变也会报错。

    const USER_NAME;//报错
    const USER_ID = '410100';USER_ID = 2;//报错

    const的作用域与let命令相同:只在声明所在的块级作用域内有效

    const命令声明的常量也是不提升,同样存在暂时性死区,只能在声明的位置后面使用。
    const声明的常量,也与let一样不可重复声明。
    const其实保证的是变量存储的内存地址不得改动,对于简单的数据类型(数值,布尔,字符串),值就存在内存地址指向的位置,就等同于常量。但是对于数组、对象保存的就是一个指针,只能保证这个指针不被改变。对于内部的数据结构的变化是无法控制的。

    const ARR = [];ARR.push(1);// 可以执行ARR.length = 0;// 可以执行ARR = [];//报错
    const OBJ = {};OBJ.name = 'JASON';// 可以执行OBJ = {};//报错

    ES6 声明变量的六种方法:var function let const import class

    顶层对象:浏览器中指window Node中指global

    ES5的时候全局变量的赋值与顶层变量的赋值是同一件事。
    ES6改变了这一点除了varfunction还保持原来的方式,新的声明变量的方法不再与顶层变量挂钩。

转载地址:http://vljpo.baihongyu.com/

你可能感兴趣的文章
PHP浮点数的精确计算BCMath
查看>>
[起重机监测系统] 1、基于无线传输的桥式起重机的安全监测方案
查看>>
2014年发展计划
查看>>
QQ协议
查看>>
[Android]一个干净的架构(翻译)
查看>>
Oracle RAC安装过程中碰到的“坑”和关键点(一)
查看>>
Jmeter关联
查看>>
java的nio之:java的nio系列教程之Scatter/Gather
查看>>
linux命令之ldconfig
查看>>
Shell之sed命令
查看>>
如何让你的传输更安全——NIO模式和BIO模式实现SSL协议通信
查看>>
【云计算的1024种玩法】使用 NAS 文件储存低价获得好磁盘性能
查看>>
Android Framework Boot Up Overview(Android系统框架启动流程概述)
查看>>
聊聊 iOS 开发
查看>>
人人都应该了解的信息简史
查看>>
linux c文件操作接口
查看>>
Struts1——ActionForward对象常用设置
查看>>
H.264学习笔记之一(层次结构,NAL,SPS)
查看>>
5G时代的无线宽带新技术
查看>>
风控模型共享如何打掉黑产?
查看>>