本系列博客爲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繼承參考了這些: