JavaScript 新特性

61 阅读3分钟

析构数组

假设想把数组中的第一个值赋给一个变量,那么可以:

const [firstAnimal] = ["Horse", "Mouse", "Cat"];
console.log(firstAnimal); // Horse

列表匹配(list matching):在需要跳过的元素位置上使用逗号执行。

const [, , thirdAnimal] = ["Horse", "Mouse", "Cat"];
console.log(thirdAnimal); // Cat

对象字面量增强

与对象析构相反的是,它是把对象重新组合成一体。

const name = "Louie Butch";
const age = 18;
const info = { name, age }; // name,age现在是info的键

用对象字面量增强或重组创建对象方法:

const name = "Louie";
const age = 18;
const print = function() {
     console.log(`Mt.${this.name}'s age is ${this.age}`);   
}
const info = { name, age, print };
info.print(); // Mt.Louie's age is 18

定义对象时无须使用function关键字

const skier = {
    name: "Louie",
    sound: "Woo...",
    powerYell() {
        let yell = this.sound.toUpperCase();
        console.log(`${yell} ${yell} ${yell}!!!`);
    }
}

展开运算符

展开运算符是三个点号(...)

const peaks = ["Tallac", "Ralston", "Rose"];
const [last] = [...peaks].reverse();

console.log(last); // Rose
console.log(peaks.join(",")); // Tallac,Ralston,Rose

reverse函数会改变原数组,所以[...peaks]创建一个peaks副本,以免改变原数组。

函数参数的收集

function directions(...args) {
    const [start, ...remaining] = args;
    const [finish, ...stops] = remainning.reverse();
    console.log(`the direction is ${finish}`); // Tahoma
}

directions("Truckee", "Tahoe City", "Homewood", "Tahoma");

异步编程

使用fetch处理简单的promise

console.log(fetch("https://api.Louie?results=1"));

此时控制台会输出一个挂起的promise,它是一个对象,表示异步操作的状态是挂起、已完成或是失败。 fetch的结果需要用一个then()函数的回调函数来做进一步的操作。

fetch("https://api.Louie?results=1").then(res => {
    console.log(res.json());
});

不管回调函数返回什么,都将作为下一个then函数的参数,因此可以串接多个then函数处理成功的promise。

fetch("https://api.Louie?results=1")
    .then(res => res.json())
    .then(json  => json.results)
    .then(console.log)
    .catch(console.error);

fetch 的 GET请求,如果请求成功,把响应主体转换成JSON格式,返回得到的JSON结构,再把结果发给console.log函数输出到控制台。catch函数,在fetch获取数据过程中出现的所有错误都将用这个回调进行处理。

async/await

const getFakerPerson = async () => {
    try {
        const res = await fetch("https://api.Louie?results=1");
        const { results } = res.json();
        console.log(results);
    } catch (error) {
        console.log(error);
    }
};

async 和 await 要成对使用,要把 promise 调用放在 try...catch块中,处理 promise 失败时可能出现的错误。

构建 promise

const getPeople = count => 
    new Promise((resolves, rejects) => {
        const api = `https://api.Louie?results=${count}`;
        const request = new XMLHttpRequest();
        request.open("GET", api);
        request.onload = () => 
            request.status === 200
                ? resolves(JSON.parse(request.response).results)
                : rejects(Error(request.statusText));
        request.onerror = err => rejects(err);
        request.send();
    });
    
getPeople(200).then(members => console.log(members)).catch(err => console.log(err.message));

JavaScript 使用原型继承实现一种类似面向对象的结构。构造函数需要使用 new 运算符调用。

function Vacation(destination, length) {
    this.destination = destination;
    this.length = length;
}

Vacation.prototype.print = function() {
    console.log(`${this.destination} | ${this.length} days`);
}

const maui = new Vacation("Maui", 7);

maui.print(); // Maui | 7 days

ES2015引入了类声明句法,JavaScript 的运作方式并没有变。函数还是对象,继承仍通过原型处理。类就像是在糟糕的原型句法上套了一层句法糖。

class Vacation {
    constructor(destination, length) {
        this.destination = destination;
        this.length = length;
    }
    
    print() {
        console.log(`${this.destination} will take ${this.length} days`);
    }
}

const trips = new Vacation("Santiago, Chile", 7);
trip.print(); // Santiago, Chile will take 7 days

类可以扩展,可以把 Vacation 当成一个抽象类,在此基础上创建不同程度的度假类型:

class Expedition extends Vacation {
    constructor(destination, length, gear) {
        super(destination, length);
        this.gear = gear;
    }
    print(){
        super.print();
        console.log(`Bring your ${this.gear.join(" and your ")}`);
    }
}

const trip = new Expedition("Mt. Whitney", 3, ["sunglasses", "prayer flags", "camera"]);

trip.prnt();

// Mt. Whitney will take 3 days
// Bring your sunglasses and your prayer flags and your camera

ES6 模块

JavaScript 模块 (module) 是一组可重用的代码,方便插入其他 JavaScript 文件而不产生变量冲突。JavaScript 模块保存在单独的文件中,一个文件一个模块。创建和导出模块有两种选择: 从一个模块中导出一个或从一个模块中导出多个 JavaScript 对象(原始类型、对象、函数、数组)。

// 导出多个对象
export const print1 = (msg) => console.log(msg);
export const print2 = (msg) => console.log(msg);

// 导出单个主变量
export defalt new Expedition("Mt. Freel", 2, ["water", "snack"]);
// 引入
// 多个引入
import { print1, print2 } from "./helps";
// 单个引入
import freel from "./freel";

print1("Hello World1");
print2("Hello World2");

freel.print();

导入的模块变量在当前模块中可以放在其他变量名下:

import { print1 as p1, print2 as p2 } from "./helps";

p1("Hello World1");
p2("Hello World2");

也可以用 * 把一切都导入为一个变量

import * as helps from "./helps";
helps.print1("Hello World1");
helps.print2("Hello World2");

CommonJS

CommonJS 是所有 Node 版本都支持的模块模式。Babel 和 Webpack 也支持这种模块。在 CommonJS 中,JavaScript 对象用 module.exports 导出。

// 导出
const print1 = (msg) => console.log(msg);
const print2 = (msg) => console.log(msg);

module.exports = { print1, print2 };
// 导入
const { print1, print2 } = require("./helps");

print1("Hello World1");
print2("Hello World2");

CommonJS 不支持 import 语句,只能使用 require 函数导入。