ES6 必知必会

285 阅读6分钟

ES6

ES6 语法基础

let 命令

  • 基本语法

    ES6 新增了 let 命令,用来声明变量。它的用法类似于 var,区别在于 let 命令声明的变量只在 let 命令所在的代码块内有效。

  • 不存在变量提升

    let 不像 var 那样,会发生“变量提升”现象。

  • 暂时性死区

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

  • 不允许重复声明

    let 不允许在相同作用域内,重复声明同一个变量。

块级作用域

  • 为什么需要块级作用域?

    ES5 只有全局作用域和函数作用域,没有块级作用域,这带来很多不合理的场景。

    第一种场景:内层变量可能会覆盖外层变量。

    第二种场景:用来计数的循环变量泄露为全局变量。

  • ES6 的块级作用域

    let 实际上为 JavaScript 新增了块级作用域。

立即执行函数

(function () {}());

const 命令

const 也用来声明变量,但是声明的是常量。一旦声明,常量的值就不能改变。const 声明的常量只在当前代码块有效。

声明冻结对象(也就是说对象的成员变量的值也不可以改变)

const person = Object.freeze({
  name: "zhangsan",
  age: 20
});

彻底冻结对象的函数

freeze.js

var constantize = (obj) => {
  Object.freeze(obj);
  Object.keys(obj).forEach((key, value) => {
    if(typeof obj[key] === 'object') {
      constantize(obj[key]);
    }
  })
};

跨模块常量

moduleA.js

export const HOST = "http://www.xxx.com";
export const PORT = 8080;
export const NAME = "Lark";

在 moduleB.js 中要如何使用 moduleA.js 中的 HOST 常量呢?

moduleB.js

// * 表示全部引入
import * as ma from "./moduleA";
// 这样使用moduleA中的变量
console.log(ma.HOST);

// 部分引入
import { HOST, PORT } as ma from "./moduleA";

console.log(ma.HOST, ma.PORT);

// 只引入一个
import NAME as ma from "./moduleA";

console.log(ma.NAME);

全局对象的属性

全局对象是最顶层的对象,在浏览器环境指的是 window 对象,在 node.js 中指的是 global 对象,在 JavaScript 语言中,所有全局变量都是全局对象的属性。(node 的情况比较特殊,这一条只对 REPL 环境适用,模块环境必须显式声明成 global 的属性)

ES6 规定,varfunction 命令声明的全局变量,属于全局对象的属性;letconstclass 命令声明的全局变量,不属于全局对象的属性。

例如:

var varName = "varValue";

// 浏览器环境下
console.log(window.varName);
// node.js环境下
console.log(global.varName);
// 通用环境下
console.log(this.varName);

结构赋值

数组的结构赋值

  • Destructuring

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

  • 不完全解构

    等号左边的模式,只匹配一部分的等号右边的数组。

  • 指定默认值

    注意:ES6内部使用严格相等运算符(===)判断一个位置是否有值。所以,如果一个数组成员不严格等于undefined,默认值是不会生效的。

  • letconst 命令

    只要某种数据结构具有 iterator 接口,都可以采用数组形式的解构赋值。

// Destructuring
// ES6
var [a, b, c] = [1, 2, 3];
console.log(a, b, c);// 1 2 3

//不完全解构
var [first, second] = [1];
console.log(first); //1
console.log(second); //undifined

//指定默认值
var [one = "One", two] = [];
console.log(one); // One
console.log(two); // undefined

var [x = "abc", y] = [undefined, "xyz"];
console.log(x); //abc 因为undefined表示没有值,所以并不会覆盖abc
console.log(y); //xyz

// iterator 接口
let [a, b, c] = new Set(["a", "b", "c"]);
console.log(a); //a
console.log(b); //b
console.log(c); //c

function* fibs() {
    let a = 0;
    let b = 1;
    while(true) {
        yield a;
        [a, b] = [b, a + b];
    };
    var [first, second, third, fourth, fifth, sixth] = fibs();
    console.log(sixth); //5
}

对象的解构赋值

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

    对象的属性没有次序,变量必须于属性同名,才能取到正确的值。

  • 指定默认值

    默认值生效的条件是:对象的属性值严格等于undefined(也就是说如果有值的话,默认值就不会生效)。

  • 现有对象的方法

    对象的解构赋值,可以很方便地将现有对象的方法赋值到某个变量。

var {name, age} = {name: "Lark", age: 30};
console.log(name, age); // Lark 30

如果变量名和属性名不一致,该如何调用?

var {name: pName, age: pAge} = {name: "Lark", age: 30};
console.log(pName, pAge); // Lark 30

指定默认值

var { x = 3 } = {};

console.log(x); // 3

var { y = 4 } = { y = undefined };
console.log(y); // 4

var { z = 5 } = { z = null };
console.log(z); // null

对已声明变量的解构赋值

var x;
{ x } = { x: 1 };
console.log(x); // 报错 语法错误,编译不通过

var y;
({ y } = { y: 1 });
console.log(y); // 1

现有对象的方法(使用现有对象的方法,就不用每次对象.方法方式调用了)

let { sin, cos, tan, PI } = Math;
console.log(sin(PI / 6)); // 0.49999999

字符串的解构赋值

  • 字符串也可以解构赋值

    字符串被转换成了一个类似于数组的对象

  • 属性解构赋值

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

var { a, b, c, d, e } = "hello";
console.log(a, b, c, d, e); // h e l l o

字符串的属性解构

const { length: len } = "hello";
console.log(len); // 5

函数参数的解构赋值

  • 函数的参数也可以使用解构
  • 函数参数的解构也可以使用默认值

函数参数的解构赋值

function sum([x, y]) {
    return x + y;
}
console.log(sum([1, 3])); // 4

函数参数解构赋值的默认值

function sum({x = 0, y = 0} = {}) {
    return [x, y];
}
console.log(sum({x: 100, y: 200})); // [100, 200]
console.log(sum({x: 100})); // [100, 0]
console.log(sum({})); // [0, 0]
console.log(sum()); //[0, 0]
function sum({x, y} = {x: 0, y: 0}) {
    return [x, y];
}
console.log(sum({x: 100, y: 200})); // [100, 200]
console.log(sum({x: 100})); // [100, undefined]
console.log(sum({})); // [undefined, undefined]
console.log(sum()); //[0, 0] 没有传参数,它做的不是函数参数解构赋值,而是对象解构赋值,{x, y} = {x: 0, y: 0} 会在函数运行。

解构赋值的用途

  • 交换变量的值
  • 从函数返回多个值
  • 函数参数的定义
  • 提取json数据
  • 函数参数的默认值
  • 遍历map解构
  • 输入模块的指定方法

交换变量的值

var x = 100;
var y = 200;
[x, y] = [y, x];
console.log(x, y); // 200 100

从函数返回多个值

function fun() {
    return [1, 2, 3];
}
var [x, y, z] = fun();
console.log(x, y, z); // 1 2 3
function fun() {
    return {
        id: "001",
        name: "Lark",
        age: 30
    };
}
var { id, name, age } = fun();
console.log(id, name, age); // 001 Lark 30

函数参数的定义

// 参数是一组有次序的值
function fun([x, y, z]) {
    // x=100 y=200 z=300
}
fun([100, 200, 300]);

// 参数是一组无次序的值
function fun2({id, name, age}) {
    // id="001" name="Lark" age=30
}
fun2({id: "001", name: "Lark", age: 30});

提取json数据

var jsonData = {
    id: "001",
    name: "Lark",
    age: 30,
    score: {
        Chinese: 100,
        English: 90
    }
};

let { id, name, age, score } = jsonData;
console.log(id, name, age, score);// 001 Lark 30 

函数参数的默认值

jQuery.ajax({
    url: '/path/to/file',
    type: 'POST',
    dataType: 'xml/html/script/json/jsonp',
    data: {param1: 'value1'},
    complete: function(xhr, textStatus) {
        
    },
    success: function(data, textStatus, xhr) {
        
    },
    error: function(xhr, textStatus, errorThrown) {
        
    }
});

jQuery.ajax = function(url, {
    async = true,
    beforeSend = function() {},
    cache = true,
    complete = function() {},
    crossDomain = false,
    global = true
}){
    // do something
};

遍历map解构

var map = new Map();
map.set("id", "001");
map.set("name", "Lark");
map.set("age", 30);

// 获取键名和键值
for(let [key, value] of map) {
    console.log(key, value);
}
// id 001
// name Lark
// age 30

// 获取键名
for(let [key] of map) {
    console.log(key);
}
// id
// name
// age

// 获取键值
for(let [, value] of map) {
    console.log(value);
}
// 001
// Lark
// 30

输入模块的指定方法

const { SourceMapConsumer, SourceNode } = require("source-map");


后面会持续更新请继续关注,再会......