zoukankan      html  css  js  c++  java
  • ES6笔记之let声明和const

    博主为什么要在繁忙的业务中抽时间写这些最基本的笔记,就是想不断积累自己小的细节,让自己的开发更有效率,不能知其然不知所以然。

    博主在实际开发中使用了react全家桶(框架)+typescript(预编译JS)+ES6(JS语法)+webpack(打包工具)+styledcomponent(css),并使用node模拟后台数据。

    因为自己不想成为写业务 的机器, 而是致力成为 技术 人员。

    ES6分类博文笔记摘自 http://es6.ruanyifeng.com/#docs/let  

    博主在这里只写最核心和自己所需要的。

    let 命令

    let命令 用来声明变量 ,与var的区别就是let所声明 的变量 作用域只在let 命令所在的代码块{}有效,且需要先声明后使用,如果直接使用会报错

    var a = [];
    for (var i = 0; i < 10; i++) {
      a[i] = function () {
        console.log(i);
      };
     a[i]();//这里依次打印0到9 }
    a[i]()//这里i从0到9都会打印10

    变量ivar声明的,在全局范围内都有效,所以全局只有一个变量i。每一次循环,变量i的值都会发生改变,

    而循环内被赋给数组afunction在运行时,会通过闭包读到这同一个变量i,(其实我这里也不是特别理解,得重新补习一下闭包)导致最后输出的是最后一轮的i的值,也就是10。

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

    变量ilet声明的,当前的i只在本轮循环有效,所以每一次循环的i其实都是一个新的变量,所以最后输出的是6。你可能会问,如果每一轮循环的变量i都是重新声明的,那它怎么知道上一轮循环的值,从而计算出本轮循环的值?这是因为 JavaScript 引擎内部会记住上一轮循环的值,初始化本轮的变量i时,就在上一轮循环的基础上进行计算。 

    另一个var和let的区别

    var命令会发生”变量提升“现象,即变量可以在声明之前使用,值为undefined。这种现象多多少少是有些奇怪的,按照一般的逻辑,变量应该在声明语句之后才可以使用。

    为了纠正这种现象,let命令改变了语法行为,它所声明的变量一定要在声明后使用,否则报错。(webstorm会自动检测,而不是在编译后检测报错,推荐使用)

    // var 的情况
    console.log(foo); // 输出undefined
    var foo = 2;
    
    // let 的情况
    console.log(bar); // 报错ReferenceError
    let bar = 2;

    上面代码中,变量foovar命令声明,会发生变量提升,即脚本开始运行时,变量foo已经存在了,但是没有值,所以会输出undefined。变量barlet命令声明,不会发生变量提升。这表示在声明它之前,变量bar是不存在的,这时如果用到它,就会抛出一个错误。

    暂时性死区

    这里原博主说了很多,但是简而言之就是如果在一个代码块中在let申明一个变量前使用了当前申请的变量,及时该变量已在外部声明,即会抛出错误。

    那有人会问了,既然抛出错误让代码不能执行,我平时用js都不会有这样的问题,那我用let的意义在哪里呢?

    为了让大家养成良好的编程习惯,变量一定要在声明之后使用,否则就报错。

    // 不报错
    var x = x;
    
    // 报错
    let x = x;
    // ReferenceError: x is not defined

    上面代码报错,也是因为暂时性死区。使用let声明变量时,只要变量在还没有声明完成前使用,就会报错。上面这行就属于这个情况,在变量x的声明语句还没有执行完成前,就去取x的值,导致报错”x 未定义“。

    ES6 规定暂时性死区和letconst语句不出现变量提升,主要是为了减少运行时错误,防止在变量声明前就使用这个变量,从而导致意料之外的行为。这样的错误在 ES5 是很常见的,现在有了这种规定,避免此类错误就很容易了。

    不允许重复声明

    let不允许在相同作用域内,重复声明同一个变量

    块级作用域

    ES5 只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。

    第一种场景,内层变量可能会覆盖外层变量。

    var tmp = new Date();
    
    function f() {
      console.log(tmp);//由于下面变量提升,即会输出undefined
      if (false) {
        var tmp = 'hello world';//没有块级作用域的限制,这里声明的tmp在ES5中会提升至函数作用域。虽然不会执行里面的赋值,但是会变量提升
      }
    }
    
    f(); // undefined

    第二种场景,用来计数的循环变量泄露为全局变量。

    var s = 'hello';
    
    for (var i = 0; i < s.length; i++) {
      console.log(s[i]);
    }
    
    console.log(i); // 5

    上面代码中,变量i只用来控制循环,但是循环结束后,它并没有消失,泄露成了全局变量。

    ES6 的块级作用域

    let实际上为 JavaScript 新增了块级作用域。

    ES6 允许块级作用域的任意嵌套。

    块级作用域与函数声明(不理解也没关系,本篇主要讲解let)

    if (true) {
      function f() {}
    }
    
    // 情况二
    try {
      function f() {}
    } catch(e) {
      // ...
    }

    上面两种函数声明,根据 ES5 的规定都是非法的。

    但是,浏览器没有遵守这个规定,为了兼容以前的旧代码,还是支持在块级作用域之中声明函数,因此上面两种情况实际都能运行,不会报错。

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

    function f() { console.log('I am outside!'); }
    
    (function () {
      if (false) {
        // 重复声明一次函数f
        function f() { console.log('I am inside!'); }
      }
    
      f();
    }());

    上面代码在 ES5 中运行,会得到“I am inside!”,因为在if内声明的函数f会被提升到函数头部,实际运行的代码如下。

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

    而在ES6中,由于f()未声明,所以会报错

    原来,如果改变了块级作用域内声明的函数的处理规则,显然会对老代码产生很大影响。为了减轻因此产生的不兼容问题,ES6在附录B里面规定,浏览器的实现可以不遵守上面的规定,有自己的行为方式

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

    注意,上面三条规则只对 ES6 的浏览器实现有效,其他环境的实现不用遵守,还是将块级作用域的函数声明当作let处理。

    const 

    const也可以用来申明变量 但是声明的是常量。一旦声明,常量的值就不能改变。

    当我们尝试去改变用const声明的常量时,浏览器就会报错。const有一个很好的应用场景,就是当我们引用第三方库的时声明的变量,用const来声明可以避免未来不小心重命名而导致出现bug:

  • 相关阅读:
    哦!Python爬虫的这4种方法优缺点你知道吗?
    当你认为Python程序慢时!几个方法你使用了吗!
    Python数据可视化你了解多少!看一下这些是你了解的吗 ?
    王者英雄你喜欢那个!利用Python网络爬虫教你抓取喜欢的英雄图片!
    使用Python时多少有人走过的坑!你是否也遇到过呢!
    Python的68个内置函数你真正的了解多少!建议合理的运用起来!
    使用Python 进行字串格式化的几种方式!你平时是否使用过呢!
    在找工作吗?今天教你使用Python网络爬虫获取招聘信息!来体验一下
    Azure上A/D系列虚拟机到DS系列迁移(1)
    超大文件上传到Azure Linux虚拟机最佳实践
  • 原文地址:https://www.cnblogs.com/studyhtml5/p/6950436.html
Copyright © 2011-2022 走看看