• 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是不能再被赋值的吗?函数会调用很多次,为什么不报错?
    其实后来一想很简单,因为函数每次执行完之后就会销毁了。。。。

  • 相关阅读:
    js判断手机端Android手机还是iPhone手机
    网站中增加微信公众账号链接的方法
    人人网的账号登录及api操作
    腾讯微博的账号登录及api操作
    QQ的账号登录及api操作
    新浪微博的账号登录及api操作
    开心网的账号登录及api操作
    豆瓣的账号登录及api操作
    判断手机旋转代码 屏幕旋转的事件和样式
    jQuery实现长按按钮触发事件的方法
  • 原文地址:https://www.cnblogs.com/mingo233/p/13561920.html
Copyright © 2020-2023  润新知