zoukankan      html  css  js  c++  java
  • JavaScript中ES6语法Let,Const变量定义解析

    一、变量提升(变量预解析)

    这是我们首先要了解的,也是必须要清楚的一个概念,那到底什么是变量提升呢?

    JavaScript 代码是由浏览器中的 JavaScript 解析器来执行的。JavaScript 解析器在运行 JavaScript 代码的 时候分为两步:预解析和代码执行
    l 预解析:在当前作用域下, JS 代码执行之前,浏览器会默认把带有 var 和 function 声明的变量在内存中 进行提前声明或者定义。
    l 代码执行: 从上到下执行JS语句。

    JS代码运行的时候确实是一行一行执行的,但是在实行前会有一个预解析的过程,相当于把所有的代码先全部扫描一遍,把带有 var 和 function 声明的变量先存在内存中,也可以说提到整体的代码前面去。
    学习预解析能够让我们知道为什么在变量声明之前 访问变量的值是 undefined,为什么在函数声明之前就可以调用函数。

    我们来看一段简单的代码

      console.log(num); // 结果是多少?         
      var num = 10; // ?
    

    答案很简单是undefined
    为什么?

    1变量提升

    变量的声明会被提升到当前作用域的最上面,变量的赋值不会提升。

    所以我们来看一下这段代码的解析过程

    其实相当于
    Var num;
    Log(num);
    num = 10;
    

    2函数提升

    函数的声明会被提升到当前作用域的最上面,但是不会调用函数。

    fn(); 
    function fn() { 
    console.log('123');
    }
    

    答案:123

    3相关例题

    接着我们看几个相关案例题

    案例一

    结果是几?

    var num = 10; 
    function fn(){ 
    console.log(num); 
    var num = 20; 
    console.log(num); 
    }
    fn();
    

    undefined
    20

    案例二

    结果是几?

    var a = 18; 
    f1(); 
    function f1() { 
    var b = 9; 
    console.log(a); 
    console.log(b); 
    var a = '123'; 
    }
    

    undefined
    9

    案例三

    结果是几?

    f1(); 
    console.log(c); 
    console.log(b); 
    console.log(a); 
    function f1() { 
    var a = b = c = 9;  
    console.log(a); 
    console.log(b); 
    console.log(c); 
    }
    

    9
    9
    9
    9
    9
    报错

    这里提一下:var a = b = c = 9; 这句话的本质上是这样的
    Var a=9,b=9,c=9
    注意 只有a是用了var的 ,所以a是局部变量,b c是全局变量

    如果要集体申明应该是var a=9,b=9,c=9。但是其实现在实际开发中var用的很少。

    二、Let

    ES6中新增的用于声明变量的关键字。
    特点:
      A、不会进行预解析,结果会报错
      B、与forEach()中的变量类似,每次执行都会定义一个互相之间不影响的新变量
      C、不能重复定义变量名称,一个变量名称只能定义一次
      D、定义的变量如果在{}中,则只能在{}中被执行调用,其他位置都不可以。所以在不同{}中,定义的变量名称是可以重复之用的
      E、在循环中最好只用let定义

    • let声明的变量只在所处于的块级有效

    注意:使用let关键字声明的变量才具有块级作用域,使用var声明的变量不具备块级作用域特性。

    if (true) { 
    let a = 10; 
    } 
    console.log(a) // a is not defined 
    
    • 不存在变量提升
    console.log(a); // a is not defined 注意这个地方是会报错的,而不是undefined
    let a = 20; 
    
    • 暂时性死区
      Let会使当前的作用域形成块级作用域,也就是说当if里面使用了let后,
      括号里面的tmp和外面申明的tmp完全没有关系了,这也叫暂时性死区
    var tmp = 123; 
    if (true) { 
    tmp = 'abc'; // tmp is not defined 
    let tmp;    
    } 
    

    let经典面试题

    var arr = []; 
    for (var i = 0; i < 2; i++) { 
    arr[i] = function () { 
    console.log(i); 
    } 
    } 
    arr[0](); 
    arr[1](); 
    
    

    答案:2 2

    此题的关键点在于变量i是全局的,函数执行时输出的都是全局作用域下的i值。
    打印i是会向上查找i的申明,但是只查到了循环体中的全局申明,所以i是全局变量
    当下面数组调用函数时,for循环早就遍历完了,此时的i已经是2了

    let经典面试题

    let arr = []; 
    for (let i = 0; i < 2; i++) { 
    arr[i] = function () { 
    console.log(i); 
    } 
    } 
    arr[0](); 
    arr[1](); 
    

    此题的关键点在于每次循环都会产生一个块级作用域,每个块级作用域中的变量都是不同的, 函数执行时输出的是自己上一级(循环产生的块级作用域)作用域下的i值

    每个块级作用域都是相互独立的,不受相互影响的

    三、Const

    作用:声明常量,常量就是值(内存地址)不能变化的量。

    特点:
    A、在js中,const定义的变量成为常量,不能被重复赋值,数据已经定义,不能修改
      B、const也是定义在{}中,不能在{}外调用
      C、const定义的是对象、数组、函数、引用数据类型。其中只要引用数据类型的地址没变化,就可以改变引用数据类型中的单元存储的数据
      D、const不会进行预解析,结果会报错

    • 具有块级作用域
    if (true) { 
    const a = 10; 
    } 
    console.log(a) // a is not defined 
    
    • 声明常量时必须赋值
    const PI; // Missing initializer in const declaration
    
    • 常量赋值后,值不能修改。

    声明了一个常量,代表这个识别名称的参照(reference)是唯读的(read-only),并不代表这个参照赋到的值是不可改变的(immutable),"const"只是针对存取层级的限制(access limitations),并不是不可改变性(immutability)。

    上面这段在讲什么呢?实际上就是简单数据类型例如字符、数值常量赋值后不能更改,但是复杂数据类型,例如数组、对象,情况有所出入。
    当对整个数组或者对象进行重新赋值时,是不被允许的,而修改里面的属性时是可以的,例如案例代码所示。
    本质原理就是常量值对应的内存地址并不能变化,重新赋值等于修改内存地址,而修改属性则没有关系。

    const PI = 3.14; 
    PI = 100; // Assignment to constant variable. 
    const ary = [100, 200]; 
    ary[0] = 'a'; 
    ary[1] = 'b'; 
    console.log(ary); // ['a', 'b']; 
    ary = ['a', 'b']; // Assignment to constant variable.
    

    额外

    1声明常量时建议使用const还是let

    这个问题网上的争议很多,有人说使用const有人说使用let,我仅我个人的理解来说我一下我的认识。

    我喜欢还是用const (这是一个非常个人化主观化的观点,你说你喜欢用let当然可以)

    • const可以用在对象、数组与函数上,常量一声明时就要赋值,犯错的机会会减少很多。

    • JS引擎也可以作优化。虽然JS语言上并没有感受差异,但实际上引擎里有区分出常量与变量,而最重要的是因为JS语言是弱(动态)类型的脚本语言,常量一声明就赋值,代表它立即决定好是什么类型与值,自然效能比变量好得多。也可以理解说因为const声明的常量是固定的,内存不需要实时监测值的变化,所以比其他变量的内存占有率更少

    2函数方法中的const

    我不知道有没有人和我一样,有一段时间一直有个困惑,就是在函数中,或者方法中,用const申明变量,不是说const是不能再被赋值的吗?函数会调用很多次,为什么不报错?
    其实后来一想很简单,因为函数每次执行完之后就会销毁了。。。。

  • 相关阅读:
    vmware ubuntu 异常关机无法连接到网络
    Speed up GCC link
    常用的一些解压命令
    Log4j 漏洞复现
    Test Case Design method Boundary value analysis and Equivalence partitioning
    CCA (Citrix Certified Administrator) exam of “Implementing Citrix XenDesktop 4”
    What is Key Word driven Testing?
    SAP AGS面试小结
    腾讯2013终端实习生一面
    指针的引用
  • 原文地址:https://www.cnblogs.com/mingo233/p/13561920.html
Copyright © 2011-2022 走看看