美文网首页前端面试题ECMAScript 6 入门
ECMAScript 6 入门--let、const和变量解构

ECMAScript 6 入门--let、const和变量解构

作者: Demonskp | 来源:发表于2019-07-15 00:19 被阅读0次

    ECMAScript 6 入门--let、const和变量解构

    主要是阅读阮一峰老师的《ES6标准入门》这一本书所做的读书笔记。作为掌握ES6相关特性的一个过程。同时也作为之后速查的一个手册。
    

    《ECMAScript 6 入门》 购买

    ES6简介

      ECMAScript和JavaScript的关系ES6是JavaScript的一个标准,是由ECMA组织制定的。而JavaScript是ECMAScript的其中一种实现。
      ES6是ECMAScript的一个版本,而ES6包含了ES2015和ES2016两个版本(在这之后ECMA决定,每年六月份发一个版本以后都按照年份来命名)
    

    let命令

    let:用来生成只能在当前代码块有效的变量
    

    当前有效

    let只在当前的代码块当中有效

    {
      let a = 10;
      var b = 1;
    }
    
    a // ReferenceError: a is not defined.
    b // 1
    

    变量提升

    let不会发生变量提升的现象,使用必须在声明之后。而不是在声明前使用视为undefined。

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

    暂时性死区

    只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。

    var tmp = 123;
    
    if (true) {
      tmp = 'abc'; // ReferenceError
      let tmp;
    }
    

    如果在代码块当中声明了一个变量,那么在当前代码块声明前的区域则会变成死区,无法在这个区域使用这个变量,即使有一个同名的全局变量。除非用this指明。

    对于某一些死区,则不是很明显。这也是容易出现错误的位置。

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

    这里在指定给bar函数的参数设置了默认值(具体请参照ES6函数新增部分),而在声明y之前就已经使用了x=y。这显然违反了暂时性死区的规则。(由此可见,可以认为在设置默认值的时候使用的是let)

    块级作用域

    块级作用域是ES6提出的一个新概念,表明用{}花括号包裹起来的区域作为一个一个域。

    解决了什么问题?

    内层变量可能会覆盖外层变量

    var tmp = new Date();
    
    function f() {
      console.log(tmp);
      if (false) {
        var tmp = 'hello world';
      }
    }
    
    f(); // undefined
    

    由于var tmp = 'hello world';导致的变量提升则console.log(tmp)当中的tmp被当成了之后声明的。于是变成了undefined。

    用来计数的循环变量泄露为全局变量

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

    本来只应该在内部循环使用的计数器泄漏到了外部。

    块级作用域这个概念就是为了let这种声明方式而提出的,let只能在其声明的作用域当中起作用。程序中只要你清楚let会在哪个位置起作用就行了,而不必纠结块级作用域这个概念。
    

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

    const命令

    const:静态变量,只能赋值一次,声明时必须赋值

    const的作用域和let是一致的,只能在声明他的作用域当中起作用。同样存在暂时性死区,不可重复性声明。

    const的本质

    const实际上保证的,并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。对于简单类型的数据(数值、字符串、布尔值),值就保存在变量指向的那个内存地址,因此等同于常量。但对于复合类型的数据(主要是对象和数组),变量指向的内存地址,保存的只是一个指向实际数据的指针,const只能保证这个指针是固定的(即总是指向另一个固定的地址),至于它指向的数据结构是不是可变的,就完全不能控制了。因此,将一个对象声明为常量必须非常小心。
    
    const foo = {};
    
    // 为 foo 添加一个属性,可以成功
    foo.prop = 123;
    foo.prop // 123
    
    // 将 foo 指向另一个对象,就会报错
    foo = {}; // TypeError: "foo" is read-only
    

    const声明的是一个地址指向,而这个地址实际存储了什么,是不被限定的。因此你能够给对象添加属性,给数组添加成员。

    变量解构

    ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值,这被称为解构(Destructuring)。

    数组解构

    let [a, b, c] = [1, 2, 3];
    a  // 1
    b  // 2
    c  // 3
    
    let [foo, [[bar], baz]] = [1, [[2], 3]];
    foo // 1
    bar // 2
    baz // 3
    
    let [ , , third] = ["foo", "bar", "baz"];
    third // "baz"
    
    let [x, , y] = [1, 2, 3];
    x // 1
    y // 3
    
    let [head, ...tail] = [1, 2, 3, 4];
    head // 1
    tail // [2, 3, 4]
    
    let [x, y, ...z] = ['a'];
    x // "a"
    y // undefined
    z // []
    
    let [x, y] = [1, 2, 3];
    x // 1
    y // 2
    

    相对应的位置有值则能够解构,没有值则无法结构,注意前一项比后一项多也可以结构。

    数组能够解构的本质是其转为对象以后具备 Iterator 接口或本身具备 Iterator 接口

    对象

    对象的解构与数组有一个重要的不同。数组的元素是按次序排列的,变量的取值由它的位置决定;而对象的属性没有次序,变量必须与属性同名,才能取到正确的值。

    let { bar, foo } = { foo: "aaa", bar: "bbb" };
    foo // "aaa"
    bar // "bbb"
    
    let { baz } = { foo: "aaa", bar: "bbb" };
    baz // undefined
    

    如果变量名与属性名不一致,必须写成下面这样。

    let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
    baz // "aaa"
    
    let obj = { first: 'hello', last: 'world' };
    let { first: f, last: l } = obj;
    f // 'hello'
    l // 'world'
    

    字符串

    字符串也可以解构赋值。这是因为此时,字符串被转换成了一个类似数组的对象。

    const [a, b, c, d, e] = 'hello';
    a // "h"
    b // "e"
    c // "l"
    d // "l"
    e // "o"
    

    类似也可以把字符串当成一个对象

    let {length : len} = 'hello';
    len // 5
    

    数值和布尔值

    解构赋值时,如果等号右边是数值和布尔值,则会先转为对象。

    let {toString: s} = 123;
    s === Number.prototype.toString // true
    
    let {toString: s} = true;
    s === Boolean.prototype.toString // true
    

    函数

    function add([x, y]){
      return x + y;
    }
    
    add([1, 2]); // 3
    

    默认值

    解构赋值允许指定默认值,与函数参数一样

    let [foo = true] = [];
    foo // true
    
    let [x, y = 'b'] = ['a']; // x='a', y='b'
    let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'
    ...
    // 其他类型都可以
    

    相关文章

      网友评论

        本文标题:ECMAScript 6 入门--let、const和变量解构

        本文链接:https://www.haomeiwen.com/subject/igbwkctx.html