本系列博客为ES6基础语法的使用及总结,若有错误,欢迎指正。 重学ES6基础语法(五)主要包括 ES6模块化、ES6的继承、遍历器等。html
历史上,JavaScript 一直没有模块(module)体系,没法将一个大程序拆分红互相依赖的小文件,再用简单的方法拼装起来。前端
在 ES6 以前,社区制定了一些模块加载方案,最主要的有 CommonJS 和 AMD 两种。前者用于服务器,后者用于浏览器。ES6 在语言标准的层面上,实现了模块功能,并且实现得至关简单,彻底能够取代现有的 CommonJS 和 AMD 规范,成为浏览器和服务器通用的模块解决方案。es6
在过去为了支持JS模块化,可使用类、当即执行函数或者第三方插件(RequireJS、seaJS)来实现模块化编程
(1) AMD数组
全称:Asynchronous Module Definition(异步模块定义)浏览器
(2) CMDbash
全称:Common Module Definition(通用模块定义)服务器
(3) AMD 和CMD 两者异同网络
相同:AMD 和 CMD都是浏览器端的js模块化规范app
异同:
CommonJS是服务端模块的规范,NodeJS采用了这个规范。 CommonJS规范同步加载模块,也就是:只有加载完成,才能执行后面的操做。
module transport
规范暴露接口,即经过返回一个对象来暴露模块接口;CommonJS的风格是经过对module.exports
或exports
的属性赋值来达到暴露模块对象的目的模块功能主要由两个命令构成:export
和import
。export
命令用于规定模块的对外接口,import
命令用于输入其余模块提供的功能。
一个模块就是一个独立的文件。该文件内部的全部变量,外部没法获取。若是你但愿外部可以读取模块内部的某个变量,就必须使用export关键字输出该变量。
1.常规导出
//分开导出
export let firstName = 'Michael';
export let lastName = 'Jackson';
export let year = 1958;
//一次性导出
let firstName = 'Michael';
let lastName = 'Jackson';
let year = 1958;
export {firstName, lastName, year};
复制代码
2.一般状况下,export
输出的变量就是原本的名字,可是可使用as
关键字重命名。
变量名被修改后原有变量名自动失效
function v1() { ... }
function v2() { ... }
export {
v1 as streamV1,
v2 as streamV2,
v2 as streamLatestVersion
};
复制代码
1.export default
命令,为模块指定默认输出。
export default function () {
console.log('foo');
}
复制代码
上面代码是一个模块文件,它的默认输出是一个函数。
其余模块加载该模块时,import
命令能够为该匿名函数指定任意名字,不须要知道原模块输出的函数名。
2.注意点
一个模块只能使用一次默认导出, 屡次无效
默认导出时, 导入的名称能够和导出的名称不一致
使用export
命令定义了模块的对外接口之后,其余 JS 文件就能够经过import
命令加载这个模块。
1.常规导入
import
命令接受一对大括号,里面指定要从其余模块导入的变量名。大括号里面的变量名,必须与被导入模块对外接口的名称相同。
import {firstName, lastName, year} from '那个js文件的路径';
复制代码
2.若是想为输入的变量从新取一个名字,import
命令要使用as
关键字,将输入的变量重命名。
import { lastName as surname } from '那个js文件的路径';
复制代码
3.注意点
import
后面的from
指定模块文件的位置,能够是相对路径,也能够是绝对路径,.js路径能够省略。import
命令能够为该匿名函数指定任意名字;不须要知道原模块输出的函数名。// export-default.js
export default function () {
console.log('foo');
}
// import-default.js
import customName from './export-default';
customName(); // 'foo'
复制代码
1.在ES6以前经过构造函数来定义一个类
function Person(myName, myAge) {
// 实例属性
this.name = myName;
this.age = myAge;
// 实例方法
this.say = function () {
console.log(this.name, this.age);
}
// 静态属性
Person.num = 666;
// 静态方法
Person.run = function () {
console.log("run");
}
}
let p = new Person("zs", 18); //建立一个Person实例
p.say(); //调用实例方法,访问实例属性
console.log(Person.num); //访问静态属性
Person.run(); //调用静态方法
复制代码
实例属性/实例方法
经过实例对象访问的属性,称之为实例属性;
经过实例对象调用的方法,称之为实例方法。
静态属性/静态方法
经过构造函数访问的属性,称之为静态属性;
经过构造函数调用的方法,称之为静态方法。
2.ES6引入了Class(类)这个概念,做为对象的模板。
经过class关键字,能够定义类。基本上,ES6的class能够看做只是一个语法糖,它的绝大部分功能,ES5均可以作到,新的class写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已。
2.1 定义类的两种方式
//方式一
class User{
···
}
//方式二
const List = class{
···
};
复制代码
2.2 类是一种特殊的函数
typeof
检查类返回function
class User{
}
console.log(typeof User); //function
复制代码
2.3 上面的代码用ES6的“类”改写,就是下面这样:
class Person{
constructor(myName, myAge){
this.name = myName;
this.age = myAge;
}
// 定义实例方法
say(){
console.log(this.name, this.age);
}
// 定义静态方法
static run() {
console.log("run");
}
}
let p = new Person("zs", 18); //建立一个Person实例
p.say(); //调用实例方法
Person.run(); //调用静态方法
复制代码
3.constructor
方法
constructor方法是类的默认方法,经过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,若是没有显式定义,一个空的constructor方法会被默认添加。
constructor
意义:类初始化时候执行的函数constructor
中添加4.在类里面定义方法注意点
static
关键字表示定义静态方法;ES6明确规定,Class内部只有静态方法,没有静态属性。constructor
外面,默认是添加到原型上面的class Point {
constructor(){
// ...
}
toString(){
// ...
}
toValue(){
// ...
}
}
// 等同于
Point.prototype = {
toString(){},
toValue(){}
};
复制代码
1.两个关键步骤
2.三句关键代码
function Person(myName, myAge) {
this.name = myName;
this.age = myAge;
}
Person.prototype.say = function () {
console.log(this.name, this.age);
};
function Student(myName, myAge, myScore) {
// 1.在子类中经过call/apply方法借助父类的构造函数
Person.call(this, myName, myAge);
this.score = myScore;
this.study = function () {
console.log("day day up");
}
}
// 2.将子类的原型对象设置为父类的实例对象
Student.prototype = new Person();
Student.prototype.constructor = Student;
let stu = new Student("zs", 18, 99);
stu.say();
复制代码
1.Class之间能够经过extends
关键字实现继承
class b extends a
2.super
关键字
3.ES6实现继承
class Person{
constructor(myName, myAge){
this.name = myName;
this.age = myAge;
}
say(){
console.log(this.name, this.age);
}
}
// 如下代码的含义: 告诉浏览器未来Student这个类须要继承于Person这个类
class Student extends Person{
constructor(myName, myAge, myScore){
super(myName, myAge);
this.score = myScore;
}
study(){
console.log("day day up");
}
}
let stu = new Student("zs", 18, 98);
stu.say();
复制代码
4.小结
ES5的继承,实质是先创造子类的实例对象this,而后再将父类的方法添加到this上面(Parent.apply(this))。ES6的继承机制彻底不一样,实质是先创造父类的实例对象this(因此必须先调用super方法),而后再用子类的构造函数修改this。
Object.getPrototypeOf方法能够用来从子类上获取父类。
在ES6中可使用这个方法判断,一个类是否继承了另外一个类。
console.log(Object.getPrototypeOf(Student) === Person); //true
复制代码
1.什么是遍历器
遍历器是一个对象,该对象里面有一个next方法会返回给咱们须要的数据
可遍历对象就是部署了[Symbol.iterator]属性的对象
2.[Symbol.iterator]
[Symbol.iterator]
的属性const arr = ['Ann','Bob','Charlie','Dolly'];
console.log(arr);
复制代码
[Symbol.iterator]
的属性会返回一个函数[Symbol.iterator]
返回的函数执行以后会返回一个新对象Array Iterator {}
,该对象中又一个名称叫作next的方法const iterator = arr[Symbol.iterator]();
console.log(iterator);
复制代码
let res = iterator.next();
console.log(res);
let res2 = iterator.next();
console.log(res2);
let res3 = iterator.next();
console.log(res3);
let res4 = iterator.next();
console.log(res4);
复制代码
undefined
和true
let res5 = iterator.next();
console.log(res5);
let res6 = iterator.next();
console.log(res6);
复制代码
第三篇说到 ,Array.prototype.entries();
和[Symbol.iterator]();
返回的都是新的Array Iterator对象,两者等价
console.log(arr.entries());
console.log(arr[Symbol.iterator]());
复制代码
两者的返回的都是新的Array Iterator{}
对象,细微的区别在于:
.entries()
返回的Array Iterator{}
对象,再调用next()时,返回给咱们的数据中的value是以数组(即包含索引)的形式[Symbol.iterator]();
返回的Array Iterator{}
对象,再调用next()时,value返回的就是那个值Array Iterator{}
4.1 .keys
方法
顾名思义,它的Array Iterator{}
的next()
方法返回的是索引
let iterator = arr.keys();
console.log(iterator);
let res = iterator.next();
console.log(res);
let res2 = iterator.next();
console.log(res2);
let res3 = iterator.next();
console.log(res3);
复制代码
4.2 .values()
方法 顾名思义,它的Array Iterator{}
的next()
方法返回的是值
let iterator = arr.values();
console.log(iterator); //Array Iterator {}
let res = iterator.next();
console.log(res);
let res2 = iterator.next();
console.log(res2);
let res3 = iterator.next();
console.log(res3);
复制代码
(抄的,这个代码太优雅了,必须分享)
Array.prototype.myIterator = function () {
let i = 0;
let items = this;
return {
next(){
const done = i >= items.length;
const value = done ? undefined : items[i++];
return {
value,
done
}
}
}
};
复制代码
本博客部份内容ES6模块化和ES6继承参考了这些: