ECMAScript6

Posted wodeqiyuan

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ECMAScript6相关的知识,希望对你有一定的参考价值。

七、ES6模块和Class

1.ES6模块

在早期javascript没有模块体系,无法将一个大程序拆分成互相依赖的小文件,再用简单的方法拼装起来。在ES6之前,社区制定了一些模块加载方案,最主要的有CommonJSAMD两种。前者用于服务器,后者用于浏览器。

ES6在语言标准的层面上,实现了模块功能,而且实现得相当简单,完全可以取代 CommonJS AMD 规范,成为浏览器和服务器通用的模块解决方案。

模块功能主要由两个命令构成:exportimportexport命令用于规定模块的对外接口,import命令用于输入其他模块提供的功能。

 

一个模块就是一个独立的文件,外部无法获取该文件内部的所有变量,如果希望外部能够读取模块内部的某个变量,就必须使用export关键字将该变量与外部建立连接,例如:

//这是一个JS文件
let firstName = ‘Michael‘;
let lastName = ‘Jackson‘;
let year = 1958;
function multiply(x, y){ return x * y; };
export {firstName, lastName, year, multiply};

 

在一个模块中,export可以调用多次需要注意的是,export命令规定对外接口必须与模块内部变量建立对应关系,不能直接导出一个值

 

使用export命令定义了模块的对外接口以后,其他JS文件就可以通过import命令加载这个模块了,下面列举了几种常用方式:

解构导入

import {firstName, lastName, year} from ‘./profile‘;

重命名变量

import { lastName as surname } from ‘./profile‘;

重复导入

import {name} from ‘./module1‘;

import {age} from ‘./module1‘;

如果多次重复执行同一句import语句,那么只会执行一次模块代码。

模块的整体加载

import * as person from ‘./module1‘

 

使用import命令的时候,用户需要知道所要加载的变量名或函数名,否则无法加载,但是,用户肯定希望快速上手,未必愿意阅读文档,去了解模块有哪些属性和方法。为了给用户提供方便,让他们不用阅读文档就能加载模块,就要用到export default命令,为模块指定默认输出,如:export default function () { console.log(‘foo‘); }

其他模块加载该模块时,import命令可以为该匿名函数指定任意名字

import customName from ‘./export-default‘;

customName(); //‘foo’(执行成功)

显然,一个模块只能有一个默认输出,因此export default命令只能使用一次。所以,import命令后面不用加大括号,因为只可能对应一个方法或者对象。

 

如果在一个模块中,先输入后输出同一个模块,import语句可以与export语句写在一起,如:

export { foo, bar } from ‘my_module‘;

//等同于

import { foo, bar } from ‘my_module‘;

export { foo, bar };

 

2.Class

JavaScript语言中,生成实例对象的传统方法是通过构造函数。ES6提供了更接近传统语言的写法,引入了Class(类)这个概念,作为对象的模板。通过class关键字,可以定义类。

基本上,ES6class可以看作是一个语法糖(更方便易用的语法特性),它的绝大部分功能,ES5 都可以做到,新的class写法只是让对象原型的写法更加清晰、更加像面向对象编程的语法而已,所以ES6的类完全可以看作构造函数的另一种写法。

 

类的实例属性可以定义在构造函数中,例如:

class Person{
    constructor(id,name,age){
        this.id = id;
        this.name = name;
        this.age = age;
    }
}

直接在类上定义的属性是静态属性,因为ES6明确规定,Class内部只有静态方法,没有静态属性,例如:

class Foo {
}
Foo.prop = 1;
Foo.prop;        //1

 

在类中可以直接定义方法,实际上类的所有方法都定义在类的prototype属性上面。在类的实例上面调用方法,其实就是调用原型上的方法

class Point {
    constructor() { ... }
    toString() { ... }
    toValue() { ... }
}

由于类的方法都定义在prototype对象上面,所以类的新方法可以添加在prototype对象上面。Object.assign方法可以很方便地一次向类添加多个方法,例如:

class Point { 
    constructor(){ ... }
 } 
Object.assign(Point.prototype, { 
    toString() { ... },
    toValue() { ... }
});

constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。类必须使用new调用,否则会报错这是它跟普通构造函数的一个主要区别,后者不用new也可以调用执行。

类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上static关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为静态方法,例如:

class Foo {
    static classMethod() { return ‘hello‘; }
}
Foo.classMethod();        //‘hello‘

如果静态方法包含this关键字,那么这个this指的是类,而不是实例。

 

class可通过extends关键字实现继承(相当于ES5中通过修改原型链实现继承),例如:

class Animal {
    constructor(name){
        this.name = name;
    }
    sayName(){
        console.log(“my name is”,this.name);
    }
}
class Dog extends Animal{
}

子类必须在constructor方法中调用super方法相当于ES5中通过构造函数实现属性继承,否则新建实例时会报错。这是因为子类没有自己的this对象,而是继承父类的this对象,然后对其完善。如果不调用super方法,子类就得不到this对象。子类构造函数可以省略。在子类的构造函数中,只有调用super之后,才可以使用this关键字,否则会报错。

 

super这个关键字,既可以当作函数使用,也可以当作对象使用。在这两种情况下,它的用法完全不同。

当做函数使用

子类B的构造函数之中的super(),代表调用父类的构造函数。super虽然代表了父类A的构造函数,但是返回的是子类B的实例,即super内部的this指的是B,因此super()在这里相当于A.prototype.constructor.call(this)

对象

在普通方法中,指向父类的原型对象;在静态方法中,指向父类。由于super指向父类的原型对象,所以定义在父类实例上的方法或属性,是无法通过super调用的。

ES6规定,通过super调用父类的方法时,super会绑定子类的this

super.print();

//等同于

super.print.call(this);

无法直接打印出super,因为无法得知super到底是函数还是对象

 

类的prototype属性和__proto__属性

class作为构造函数的语法糖,同时有prototype属性和__proto__属性,因此同时存在两条继承链:

子类的__proto__属性,表示构造函数的继承,总是指向父类;

子类prototype属性的__proto__属性,表示方法的继承,总是指向父类的prototype属性,例如:

class A { }
class B extends A { }
B.__proto__ === A;        //true
B.prototype.__proto__ === A.prototype;    //true

 

类的继承是按下面这种模式实现的:

class A { }

class B { }

//B的实例继承A的实例

Object.setPrototypeOf(B.prototype, A.prototype);

//B的实例继承A的静态属性

Object.setPrototypeOf(B, A);

let b = new B();

以上是关于ECMAScript6的主要内容,如果未能解决你的问题,请参考以下文章

ECMAScript6语法

ECMAScript6 入门-let与const命令

React_02_ECMAScript6

ECMAScript6 初步认识

ECMAScript6 | 特性(部分)

ECMAScript6 规范