zoukankan      html  css  js  c++  java
  • ES6 介绍 及 变量的声明、解构赋值

    一、ES6 简介

    • ECMAScript 6.0(以下简称 ES6)是 ES6 是 5.1 版以后的 JavaScript 的下一代标准,涵盖了 ES2015、ES2016、ES2017

    • 语法提案的批准流程:一种新的语法从提案到变成正式标准,需要经历五个阶段,如下(一个提案只要能进入 Stage 2,就差不多肯定会包括在以后的正式标准里面)

      • Stage 0 - Strawman(展示阶段)
      • Stage 1 - Proposal(征求意见阶段)
      • Stage 2 - Draft(草案阶段)
      • Stage 3 - Candidate(候选人阶段)
      • Stage 4 - Finished(定案阶段)
    • babel转码: 一些JS运行运行环境(runtime),可能不完全支持ES6新语法,需要进行 babel 转码,将ES6语法 转为 ES5语法,从而在现有环境执行 Babel 转码器 参考

    二、ES6 新特性汇总(待补充)

    • 增加块级作用域

    • 数据类型的语法扩展

    • 语法更加严谨

      • 创建数组: Array.of(3) ---> [3]

      • 判断NaN 是否等于 NaN: Object.is(NaN, NaN) ---> true

      • +0 与 -0 不相等: Object.is(+0, -0) ---> false

    三、ES6 新增 块级作用域

    • ES6的块级作用域,是通过 letconst 声明变量,来体现的

      • 只要一个代码块 { } 中存在 letconst ,就形成了一个封闭的作用域(块级作用域)

      • 每一个 { } 都是一层块级作用域

    • 块级作用域的出现,实际上使得获得广泛应用的立即执行函数表达式(IIFE)不再必要了

    // IIFE 写法
    (function () {
        var tmp = ...;
        ...
    }());
    
    // 块级作用域写法
    {
        let tmp = ...;
        ...
    }
    

    四、变量的 声明

    1. let 、const 声明的变量 是 局部变量

    • 通过 letconst 声明的变量,只能在当前块级作用域子作用域 被访问到

    • 通过 letconst 声明的变量,window环境中不能访问到

    • ES6 规定

      • varfunction 声明的全局变量,依旧是顶层对象(window)的属性

      • letconstclass 声明的全局变量,不属于顶层对象(window)的属性

    var a = 1;
    console.log(window.a);  // 1
    
    let b = 1;
    console.log(window.b);  // undefined
    

    2. let 、const 声明变量 不存在变量提升

    • letconst 声明变量,不存在变量提升
    // var 的情况
    console.log(foo); // 输出undefined
    var foo = 2;
    
    // let 的情况
    console.log(bar); // 报错ReferenceError
    let bar = 2;
    

    3. let 、const 声明变量 不允许重复声明

    • ES6规定:
      • varfunction 声明的变量,重复声明无效,不会报错

      • letconst 、声明的变量,重复声明会报错

    // 报错
    if (true) {
        const a = 10;
        const a = 1;
    }
    
    • 细节对比:
      • 函数直接作用域内 使用 let 重新声明形参,会报错

      • 内层作用域可以定义外层作用域的同名变量,不会报错

    function func(arg) {
        let arg; // 报错
    }
    
    function func(arg) {
        {
            let arg; // 不报错
        }
    }
    

    4. let 、const 声明变量 存在暂时性死区(TDZ)

    • 暂时性死区(TDZ)
      • 块级作用域中,letconst 声明变量 之前的区域, 就是变量的 暂时性死区

      • 在变量的暂时性死区内,使用变量会报错

    var tmp = 123;
    
    if (true) {
        // TDZ开始
        tmp = 'abc'; // ReferenceError
        console.log(tmp); // ReferenceError
        
        let tmp; // TDZ结束
        console.log(tmp); // undefined
        
        tmp = 123;
        console.log(tmp); // 123
    }
    
    // 上面代码中,在let命令声明变量tmp之前,都属于变量tmp的“死区”
    
    • 比较隐蔽的暂时性死区(参数部分)
    function bar(x = y, y = 2) {
        return [x, y];
    }
    
    console.log(bar()); // 报错
    

    5. letconst 区别

    • 区别:

      • let 声明的变量 允许被修改

      • const 声明的变量 不允许被修改;意味着:const 一旦声明变量,就必须立即初始化,不能留到以后赋值,否则会报错

    let f1;     // 不报错
    
    const f2;   // SyntaxError: Missing initializer in const declaration
    
    • const 声明的本质: 并不是变量的值不得改动,而是变量指向的那个内存地址不得改动
      • 简单数据类型:值就保存在变量指向的那个内存地址,所以不能有任何改变

      • 复杂数据类型:const 声明的变量 可以改变指针中的 的数据结构

    // 所以:const 声明复杂数据类型,其数据结构是可变的
    const foo = {};
    
    // 为 foo 添加一个属性,可以成功
    foo.prop = 123;
    ondole.log(foo.prop); // 123
    

    五、变量的 解构赋值

    1. 解构赋值 --- 数组

    • 数组 解构赋值的内部机制

      • 遵循 结构 + 位置 匹配模式, 描述如下:

      • 数组的每一项都是按次序排列的,完全解构赋值时,相同位置 数据结构相同,才能成功的解构赋值; 否则值为 undefined

    • 分为:完全解构赋值、不完全解构赋值

    // 完全结构赋值
    let [foo, [[bar], baz]] = [1, [[2], 3]];
    console.log(foo);   // 1
    console.log(bar);   // 2
    console.log(baz);   // 3
    
    // 不完全结构赋值
    let [x, y] = [1, 2, 3];
    console.log(x);     // 1
    console.log(y);     // 2
    
    // `...a` 代表定义数组
    let arr = [1, 2, 3, 4];
    let [a, b, ...c] = arr;
    
    console.log(c);   // [3, 4]
    

    2. 解构赋值 --- 对象

    • 数组 解构赋值的内部机制
      • 遵循 结构 + 相同属性名 匹配模式, 描述如下:

      • 对象中的每一项并不是按顺序排列的,解构赋值时根据相同的结构 找到同名属性;将同名属性的值 赋给 定义对象的属性的值(是属性值的解构赋值),否则值为 undefined

    // 定义的变量名 与 属性名一致
    let { bar, foo } = { foo: "aaa", bar: "bbb" };
    foo // "aaa"
    bar // "bbb"
    
    const node = {
      loc: {
        start: {
          line: 1,
          column: 5
        }
      }
    };
    
    let { loc, loc: { start }, loc: { start: { line }} } = node;
    line // 1
    loc  // Object {start: Object}
    start // Object {line: 1, column: 5}
    
    • 注意: 定义的变量名 与 属性名不一致情况下
    let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
    console.log(baz);   // "aaa"
    

    3. 解构赋值 --- 数组、对象 指定默认值

    • 默认值生效的条件: 数组 / 对象 的属性值 严格等于 undefined
    let [x = 1] = [undefined];
    console.log(x);     // 1
    
    let [y = 1] = [null];
    console.log(y);     // null
    
    • 如果默认值是一个表达式,那么这个表达式是惰性求值的(只有在用到的时候,才会求值)
    function f() {
        console.log('aaa');
    }
    
    let [x = f()] = [1]; // 无输出
    let [x = f()] = [];  // aaa
    
    • 默认值可以引用解构赋值的其他变量,但该变量必须已经声
    let [x = 1, y = x] = [];     // x=1; y=1
    let [x = 1, y = x] = [2];    // x=2; y=2
    let [x = 1, y = x] = [1, 2]; // x=1; y=2
    let [x = y, y = 1] = [];     // ReferenceError
    

    3. 解构赋值 --- 字符串、数值、布尔值、null、undefined

    • 字符串:
      • 解构赋值时,字符串被转换成了一个类似数组的对象
    const [a, b, c, d, e] = 'hello';
    a // "h"
    b // "e"
    c // "l"
    d // "l"
    e // "o"
    
    • 数值、布尔值:
      • 等号右边是数值和布尔值,则会先转为对象
    let {toString: s} = 123;
    s === Number.prototype.toString // true
    
    let {toString: s} = true;
    s === Boolean.prototype.toString // true
    
    • null、undefined:
      • undefinednull 无法转为对象,所以对它们进行解构赋值,都会报错
    let { prop: x } = undefined; // TypeError
    let { prop: y } = null; // TypeError
    

    4. 解构赋值 --- 函数的参数

    • 最基本的三种形式如下:
    function fn({
        x, 
        y
    }) {
      return [x, y];
    }
    
    function fn({
        x = 0,
        y = 1
    }) {
      return [x, y];
    }
    
    function fn({
        x,
        y
    } = {
        x = 1,
        y = 2
    }) {
      return [x, y];
    }
    
    • 举例如下:
    function move({
        x = 0, 
        y = 0
    } = {}) {
      return [x, y];
    }
    
    move({x: 3, y: 8}); // [3, 8]
    move({x: 3}); // [3, 0]
    move({}); // [0, 0]
    move(); // [0, 0]
    
    function foo({
        x = 10,
        y = 5
    }) {
        console.log(x, y);
    }
    
    foo({})       // 10 5
    foo({x: 1})   // 1 5
    foo()         // TypeError: Cannot read property 'x' of undefined
    
    function foo({
        x = 10,
        y = 5
    } = {}) {
        console.log(x, y);
    }
    
    foo({})       // 10 5
    foo({x: 1})   // 1 5
    foo()         // 10 5
    

    5. 解构赋值 --- 用途

    • 交换变量
    let x = 1;
    let y = 2;
    
    [x, y] = [y, x];
    
    • 函数 设置默认参数
    function(n = 1) {
        return n;
    }
    
    • 提取 对象 中的数据
    let jsonData = {
        id: 42,
        status: "OK",
        data: [867, 5309]
    };
    
    let { id, status, data: number } = jsonData;
    
    console.log(id, status, number);
    // 42, "OK", [867, 5309]
    
  • 相关阅读:
    行星工单系统部分实现(1)-流程控制
    当初要是看了这篇,React高阶组件早会了
    健壮高效的小程序登录方案
    SQL Case when 的使用
    JS脚本动态给元素/控件添加事件
    VMware虚拟机屏幕大小只有400,800怎么办如何解决
    mysql和mysql jdbc连接器mysql-connector-java对应关系
    mysql中难以理解的sql
    PLSQL计算质数
    java alibaba fastJson 遍历数组json
  • 原文地址:https://www.cnblogs.com/zxvictory/p/8358783.html
Copyright © 2011-2022 走看看