美文网首页
了解es6(声明、解构、模板字符串)

了解es6(声明、解构、模板字符串)

作者: 锋享前端 | 来源:发表于2018-09-05 11:35 被阅读0次

    ES6简介

    ECMAScript 6.0(以下简称 ES6)是 JavaScript 语言的下一代标准,已经在 2015 年 6 月正式发布了。它的目标,是使得 JavaScript 语言可以用来编写复杂的大型应用程序,成为企业级开发语言。

    一、ES6之let和const的使用

    1.1块级作用域

    在ES5之前,不存在块级作用域,在编程的时候很多时候会带来很多的不便,ES6新增了块级作用域,补足了这方面的缺陷。

    块级声明指的是该声明的变量无法被代码块外部访问。块作用域,又被称为词法作用域(lexical scopes),可以在如下的条件下创建:

    • 函数内部
    • 在代码块(即 { })内部

    块级作用域是很多类C语言的工作机制,ECMAScript 6 引入块级声明的目的是增强 JavaScript 的灵活性,同时又能与其它编程语言保持一致。

    1.2 let声明

    使用let声明变量的语法和使用var声明的语法是一样的。但是let声明的变量的作用域会限制在当前的代码块中。这是let与var的最大区别。

    <script type="text/javascript">
        /***  var 和 ES6 let对比 ****/
            {
                var a = 10;
                let b = 20;
            }
    
            console.log(a);
            // 因为let声明后具有块级作用域 出了代码块后就访问不到 说报错
            console.log(b);
    </script>
    
    <script type="text/javascript">
        //在for循环中的使用
          for (var i = 0; i < 5; i++) {
    
          }
    
          console.log(i);
    
          for (let j = 0; j < 5; j++) {
    
          }
          //这里 j 也是存在代码块中, 这里会报错
          console.log(j);
    </script>
    
    <script type="text/javascript">
          //用var 声明的时候 有变量提升的特性
          console.log(c);
          var c = 'c';
    
          //使用let 不会有变量提升
          console.log(d);
          let d = 'd';
    </script>
    
    <script type="text/javascript">
        var e = "e";
        if (true) {
          e = "ee";
          //在代码块中,只要存在let命令,它声明的所有变量都会绑定在它身上。
          let e = "小王";
          console.log(e);
        }
    </script>
    
    总之在代码块内,使用变量之前,一定要用let声明好。
    如果let在使用变量之后声明的话,我们称为:"暂时性死区" (temporary dead zone,简称:TDZ)。
    
    <script type="text/javascript">
        if (true) {
          //TDZ 开始
          d = "d";
          console.log(d)
          //TDZ 结束
          let d = "dd";
          console.log(d);
        }
    </script>
    
    let不允许在同一作用域中声明重复的变量
    
    <script type="text/javascript">
        (function () {
          let a = "a";
          //let a = "b";
        })();
    
        (function () {
          let a = "a";
          //var a = "b";
        })();
                    
        (function (arg) {
          //let arg = "a";
        })();
                    
        (function (arg) {
          {
            //自己在独立的一个块级里,就不会和形参的arg有冲突了。
            let arg = "a";
          }
        })();
    </script>
    
    关于全局变量,在var声明的情况下,全局变量就等同于全局对象的属性,用ES6的let声明全局变量则不会。
    
    <script type="text/javascript">
        var str = 33;
        console.log(window.str); //33
    
        let str2 = "bcd";
        console.log(window.str2); //undefined
        console.log(str2); //bcd
    </script>
    
     利用let解决一个比较经典的问题
    
    <input type="button" value="按钮1" id="button1" />
    <input type="button" value="按钮2" id="button2" />
    <input type="button" value="按钮3" id="button3" />
    <script type="text/javascript">
        for (var z = 1; z < 4; z++) {
          var button = document.getElementById('button' + z);
            button.addEventListener('click', function () {
              alert('button' + (z));  //每次打印结果 都是 button4
            });
        }
    
        //利用函数立即执行、形成闭包。每次保存z的值 这样就可以实现我们想要的结果
        for (var z = 1; z < 4; z++) {
          var button = document.getElementById('button' + z);
          //每次循环把i存储起来
          (function (z) {
            button.addEventListener('click', function () {
              alert('button' + (z));
            });
          })(z);
        }
        
        //更简单的解决办法,形成块级作用域,使用let
        for (let z = 1; z < 4; z++) {
          var button = document.getElementById('button' + z);
            button.addEventListener('click', function () {
              alert('button' + (z));  //每次打印结果 都是 button4
            });
        }
    </script>
    

    1.3 const声明

    在 ES6 使用const来声明的变量称之为常量。这意味着它们不能再次被赋值。由于这个原因,所有的 const 声明的变量都必须在声明处初始化。

    const声明的常量和let变量一样也是具有块级作用域的特性,一样不支持变量(常量)提升,一样存在"TDZ"。
    const命令用来声明常量,常量一旦声明,就无法改变。
    const命令用来声明常量,一定要初始化。
    
    <script type="text/javascript">
        const PI = "3.1415..";
        console.log(PI);
        PI = "能修改吗?"; // 报错,常量不能修改
        console.log(PI); 
    </script>
    

    注意:针对于引用类型,修改值就是修改变量指针的指向。指向不同的对象实例

    <script type="text/javascript">
        const OBJ = {};
        //OBJ = { age : 18 };  不可以,这样相当于修改了对象的指针指向
        OBJ.name = "小雪";  //可以,这个没有修改对象的指针指向,而是修改内部的属性值
        console.log(OBJ);
                    
        //我们可以使用Object.freeze()冻结这个对象,从而达到不能操作对象的属性
        Object.freeze(OBJ);
        OBJ.age = 18;
        OBJ.name = "小虹";
        console.log(OBJ);
    </script>
    

    二、变量的解构

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

    以前,为变量赋值,只能直接指定值。

    let a = 1;
    let b = 2;
    let c = 3;
    

    ES6 允许写成下面这样。

    let [a, b, c] = [1, 2, 3];
    

    上面代码表示,可以从数组中提取值,按照对应位置,对变量赋值。

    2.1 数组的解构

    只要等号两边的模式相同,左边的变量就会被赋予对应的值。下面是一些使用嵌套数组进行解构的例子。

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

    如果解构不成功,变量的值就等于undefined。

    let [foo] = [];
    let [bar, foo] = [1];
    

    以上两种情况都属于解构不成功,foo的值都会等于undefined。

    另一种情况是不完全解构,即等号左边的模式,只匹配一部分的等号右边的数组。这种情况下,解构依然可以成功。

    let [x, y] = [1, 2, 3];
    console.log(x) // 1
    conole.log(y) // 2
    
    let [a, [b], d] = [1, [2, 3], 4];
    console.log(a) // 1
    console.log(b) // 2
    console.log(d) // 4
    

    上面两个例子,都属于不完全解构,但是可以成功。

    如果等号的右边不是可遍历的结构,那么将会报错。

    // 报错
    let [foo] = 1;
    let [foo] = false;
    let [foo] = NaN;
    let [foo] = undefined;
    let [foo] = null;
    let [foo] = {};
    

    上面的语句都会报错,因为等号右边的值,要么转为对象以后不具备 Iterator 接口(前五个表达式),要么本身就不具备 Iterator 接口(最后一个表达式)。

    2.2 对象的解构

    解构不仅可以用于数组,还可以用于对象。

    let { foo, bar } = { foo: "aaa", bar: "bbb" };
    console.log(foo) // "aaa"
    console.log(bar) // "bbb"
    

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

    let { bar, foo } = { foo: "aaa", bar: "bbb" };
    console.log(foo) // "aaa"
    console.log(bar) // "bbb"
    
    let { baz } = { foo: "aaa", bar: "bbb" };
    baz // undefined
    

    上面代码的第一个例子,等号左边的两个变量的次序,与等号右边两个同名属性的次序不一致,但是对取值完全没有影响。第二个例子的变量没有对应的同名属性,导致取不到值,最后等于undefined。

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

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

    这实际上说明,对象的解构赋值是下面形式的简写)。

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

    也就是说,对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者,而不是前者。

    let { foo: baz } = { foo: "aaa", bar: "bbb" };
    console.log(baz) // "aaa"
    console.log(foo) // error: foo is not defined
    

    上面代码中,foo是匹配的模式,baz才是变量。真正被赋值的是变量baz,而不是模式foo。

    如果要将一个已经声明的变量用于解构赋值,必须非常小心。

    // 错误的写法
    let x;
    {x} = {x: 1};
    // SyntaxError: syntax error
    

    上面代码的写法会报错,因为 JavaScript 引擎会将{x}理解成一个代码块,从而发生语法错误。只有不将大括号写在行首,避免 JavaScript 将其解释为代码块,才能解决这个问题。

    // 正确的写法
    let x;
    ({x} = {x: 1});
    

    2.3 字符串的解构

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

    const [a, b, c, d, e] = 'hello';
    console.log(a) // "h"
    cnosole.log(b) // "e"
    console.log(c) // "l"
    console.log(d) // "l"
    console.log(e) // "o"
    

    类似数组的对象都有一个length属性,因此还可以对这个属性解构赋值。

    let {length : len} = 'hello';
    console.log(len) // 5
    

    三、模板字符串

    模板字符串(template string)是增强版的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量。

    // 普通字符串
    `In JavaScript '\n' is a line-feed.`
    
    // 多行字符串
    `In JavaScript this is
     not legal.`
    
    console.log(`string text line 1
    string text line 2`);
    
    // 字符串中嵌入变量
    let name = "Bob", time = "today";
    `Hello ${name}, how are you ${time}?`
    

    相关文章

      网友评论

          本文标题:了解es6(声明、解构、模板字符串)

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