本系列博客爲ES6基礎語法的使用及總結,若有錯誤,歡迎指正。
重學ES6之出來混早晚要還的(五)主要包括 ES6模塊化、ES6的繼承、遍歷器等。html
其餘筆記:
重學ES6之出來混早晚要還的(一)
重學ES6之出來混早晚要還的(二)
重學ES6之出來混早晚要還的(三)
重學ES6之出來混早晚要還的(四)
重學ES6之出來混早晚要還的(六)
數據類型的轉換/判斷/比較前端
歷史上,JavaScript 一直沒有模塊(module)體系,沒法將一個大程序拆分紅互相依賴的小文件,再用簡單的方法拼裝起來。在 ES6 以前,社區制定了一些模塊加載方案,最主要的有 CommonJS 和 AMD 兩種。前者用於服務器,後者用於瀏覽器。ES6 在語言標準的層面上,實現了模塊功能,並且實現得至關簡單,徹底能夠取代現有的 CommonJS 和 AMD 規範,成爲瀏覽器和服務器通用的模塊解決方案。es6
在過去爲了支持JS模塊化,可使用類、當即執行函數或者第三方插件(RequireJS、seaJS)來實現模塊化編程
(1) AMDsegmentfault
全稱:Asynchronous Module Definition(異步模塊定義)數組
(2) CMD瀏覽器
全稱:Common Module Definition(通用模塊定義)服務器
(3) AMD 和CMD 兩者異同網絡
異同: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(){} };
(以上上面代碼爲例打印p這個對象,能夠發現say()方法存在在原型上)
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);
3.一點區別
第三篇說到,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返回的就是那個值
4.其餘方法返回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);
5.實現一個遍歷器
(抄的,這個代碼太優雅了,必須分享)
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繼承參考了這些: