ECMAScript 6新特征印象之二:面临对象和模块化

本文参考了以下文章/PPT:

之前的文章:

面临对象

1.关键字 Class

class Artist {
    constructor(name) {
        this.name = name;
    }
    perform() {
        return this.name + " performs ";
    }
}

class Singer extends Artist {
    constructor(name, song) {
        super.constructor(name);
        this.song = song;
    }
    perform() {
        return super.perform() + "[" + this.song + "]";
    }
}

let james = new Singer("Etta James", "At last");
james instanceof Artist; // true
james instanceof Singer; // true

james.perform(); // "Etta James performs [At last]"

看上面例子就能够邃晓。注重几个关键字extendssuper

虽然ES6的Class本质上照样语法糖,但这么设想有它的目的。

在ES5中, function关键字负担著三个职责:

  1. 定义函数。
  2. 定义要领属性。
  3. 定义类的constructor,合营new建立新对象。

在ES6中,第2点被属性要领定义(Method definitions)替换,第3点被Class关键字替换。一个关键字只负担一个职责,不再是满屏function,充足清楚了吧?

有几点要注重的:

  1. 类的body只能包括属性要领,不能包括属性值。属性值放到constructor要领里。
  2. 属性要领可所以天生器,在要领名前家*就能够够。
  3. 声明类(Class Declaration)并不会被提拔(hoisted)。
  4. 假如没有指定constructor,那会有个默许挪用super的。

2.继续 Extending

继续的几种状况和划定规矩:

  1. 不要继续空类, class Foo {},由于:

    • Foo的原型(prototype)是Function.prototype(一切函数的原型都是这个)。
    • 而Foo.prototype的原型是Object.prototype
    • 这类继续就和函数一样了。
  2. 继续nullclass Foo extends null {}

    • Foo的原型是Function.prototype
    • Foo.prototype的原型是null
    • 如许Object.prototype的属性要领都不会继续到Foo中。
  3. 继续组织器:class Foo extends SomeClass

    • Foo的原型是SomeClass
    • Foo.prototype的SomeClass.prototype
    • 如许,类要领属性也会被继续。
  4. 继续非组织器(对象):class Foo extends SomeObject

    • Foo的原型是Function.prototype
    • Foo.prototype的SomeClass
  5. 毛病搜检:继续的目的肯定如果个对象或许null。假如是继续组织器,那末组织器的原型肯定如果个对象或许null。

  6. 类声明实在建立的是可变let绑定(binding,函数式编程会比较熟习这个观点)。关于一个类Foo:

    • Foo的原型是不可改写,且不可枚举的。
    • Foo的组织器是可改写,但不可枚举。
    • Foo的原型函数(Foo.prototype.*)是可改写,但不可枚举。

模块

ES6的内置模块体系自创了CommonJS和AMD各自的长处:

  • 具有CommonJS的精简语法、唯一导出出口(single exports)和轮回依靠(cyclic dependencies)的特性。
  • 相似AMD,支撑异步加载和可设置的模块加载。

不单单议自创,ES6还对这些功用举行了优化:

  • 语法比CommonJS更精简。
  • 支撑构造的静态剖析(静态搜检,优化等等)。
  • 轮回依靠的支撑比CommonJS更好。

1.语法

ES6模块的导出出口情势有两种:定名导出(一个模块多个导出)、规范导出(一个模块一个导出)。

定名导出 Named exports

//-------lib.js----------
export const sqrt = Math.sqrt;
export function square(x) {
    return x * x;
}
export function diag(x, y) {
    return sqrt(square(x) + square(y));
}

//-------main1.js--------
import { sqaure, diag } from 'lib';

console.log(square(11)); // 121
console.log(diag(3,4)); // 5

//或许如许,定名导入的称号:
//-------main2.js--------
import * as lib from 'lib';
console.log(lib.square(11)); // 121
console.log(lib.diag(3,4)); // 5

规范导出 Default exports

//-------MyClass.js-----
// 注重,`export`的操纵对象是表达式,平常是没有名字的。
export default class { ... };

//-------main3.js--------
// 经由过程模块名字辨认
import MyClass from 'MyClass';
let inst = new MyClass();

固然,这两种导出也能够夹杂运用。本质上,规范导出只是指名导出的一种,称号是「default」罢了。

就现在相识的来看,ES6的模块导出貌似有些烦琐,还不如CommonJS直接经由过程object导出利索。

2.设想初志 Design goals

TC39在议论ES6的模块化题目时,重要斟酌了下面几点:

  1. 直接导出优先
  2. 静态模块构造
  3. 同步/异步载入都要支撑
  4. 支撑轮回依靠

第一点就是要简朴已用。而静态模块构造更多是出于机能优化、静态范例搜检(没错,就是这个,动态言语为何要有这个,实在照样为了机能)和今后的可能会到场的「宏模板」功用。

3.更多导入/导出写法举例

导入:

// 规范导入,定名导入
import theDefault, { named1, named2 } from 'src/mylib';
import theDefault from from 'src/mylib';
import { named1, named2 } from 'src/mylib';

// 重定名
import { named1 as myNamed1, named2 } from 'src/mylib';

// 将导入的模块定义为一个对象
// 模块的每一个属性都是该对象的同名要领属性
import * as mylib from 'src/mylib';

// 仅读取模块,不导入任何功用
import 'src/mylib';

导出:

// 运用关键字**export**导出
export let myVar1 = ...;
export function MyFunc() {...}
export function* myGeneratorFunc() {...}

// 也能够以对象情势导出
const MY_CONST = ...;
function myFunc() { ... }

export { MY_CONST, myFunc }
// 固然,名字不肯定要雷同
export { MY_CONST as THE_CONST, myFunc as theFunc };

// 支撑重导出,即在当前模块导出其他模块的功用 轻易hack
export * from 'src/other_module';
export { foo, bar } from 'src/other_module';

上面说的这些语法,一般的<script>标签是不支撑的。ES6引入了一个<module>标签,担任载入模块。<script>标签只能经由过程下面将要引见的模块API举行模块载入。

4.模块元数据

不单单议是导入别的数据,ES6还能经由过程导入当前模块拿到当前模块的信息:

import { url } from this module;
console.log(url);

这就像Ruby里的____FILENAME____

5.模块载入接口 Module loader API

API天然是为了经由过程代码掌握模块载入的,算是若干弥补了静态构造灵活上上的缺点。

每一个浏览器平台都邑有一个名为System的全局变量,经由过程这个变量挪用响应接口,异步载入模块(连系ES6的promises):

System.import('some_module')
.then(some_module => {
    ...
})
.catch(error => {
    ...
})

//固然也能够一次载入多个模块
Promise.all(
    ['module1', 'module2', 'module3']
).map(x => Symtem.import(x)))
.then(function([module1, module2, module3]) {
    ...
});

其他接口:

  • System.module(source, options?)将source中的代码求值成一个模块。
  • System.set(name, module)注册一个经由过程System.module天生的模块。
  • System.define(name, source, options?)前两个接口的连系。

更多关于模块的申明

请看看Yehuda Katz的这一篇:Javascript Modules

    原文作者:皓矾
    原文地址: https://segmentfault.com/a/1190000000660067
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞