ECMAScript 6教程 (三)
Class
目錄:
- Class基本語法
- Class的繼承
- class的取值函式(getter)和存值函式(setter)
- Class的Generator方法
- Class的靜態方法
- new.target屬性
- 修飾器
Module
- export命令
- import命令
- 模組的整體輸入
- module命令
- export default命令
- 模組的繼承
Class基本語法
ES6提供了更接近傳統語言的寫法,引入了Class(類)這個概念,作為物件的模板。通過class關鍵字,可以定義類。
//定義類
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '('+this.x+', '+this.y+')';
}
}
上面程式碼定義了一個“類”,可以看到裡面有一個constructor方法,這就是構造方法,而this關鍵字則代表例項物件。
constructor方法
constructor方法是類的預設方法,通過new命令生成物件例項時,自動呼叫該方法。
例項物件
var point = new Point(2, 3);
name屬性
class Point {}
Point.name // "Point"
class表示式
與函式一樣,Class也可以使用表示式的形式定義。
const MyClass = class Me {
getClassName() {
return Me.name;
}
};
Class的繼承
Class之間可以通過extends關鍵字,實現繼承。
子類會繼承父類的屬性和方法。
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
class ColorPoint extends Point {
constructor(x, y, color) {
this.color = color; // ReferenceError
super(x, y);
this.color = color; // 正確
}
}
上面程式碼中,子類的constructor方法沒有呼叫super之前,就使用this關鍵字,結果報錯,而放在super方法之後就是正確的。
注意:ColorPoint繼承了父類Point,但是它的建構函式必須呼叫super方法。
下面是生成子類例項的程式碼。
let cp = new ColorPoint(25, 8, 'green');
cp instanceof ColorPoint // true
cp instanceof Point // true
class的取值函式(getter)和存值函式(setter)
在Class內部可以使用get和set關鍵字,對某個屬性設定存值函式和取值函式。
class MyClass {
get prop() {
return 'getter';
}
set prop(value) {
document.write('setter: '+value);
}
}
let inst = new MyClass();
inst.prop = 123;
// setter: 123
inst.prop
// 'getter'
Class的Generator方法
如果某個方法之前加上星號(*),就表示該方法是一個Generator函式。
class Foo {
constructor(...args) {
this.args = args;
}
* [Symbol.iterator]() {
for (let arg of this.args) {
yield arg;
}
}
}
for (let x of new Foo('hello', 'world')) {
document.write(x);
}
// hello
// world
上面程式碼中,Foo類的Symbol.iterator方法前有一個星號,表示該方法是一個Generator函式。Symbol.iterator方法返回一個Foo類的預設遍歷器,for...of迴圈會自動呼叫這個遍歷器。
上面程式碼中,prop屬性有對應的存值函式和取值函式,因此賦值和讀取行為都被自定義了。
Class的靜態方法
類相當於例項的原型,所有在類中定義的方法,都會被例項繼承。如果在一個方法前,加上static關鍵字,就表示該方法不會被例項繼承,而是直接通過類來呼叫,這就稱為“靜態方法”。
class Foo {
static classMethod() {
return 'hello';
}
}
Foo.classMethod() // 'hello'
var foo = new Foo();
foo.classMethod()
// TypeError: undefined is not a function
上面程式碼中,Foo類的classMethod方法前有static關鍵字,表明該方法是一個靜態方法,可以直接在Foo類上呼叫(Foo.classMethod()),而不是在Foo類的例項上呼叫。如果在例項上呼叫靜態方法,會丟擲一個錯誤,表示不存在該方法。
父類的靜態方法,可以被子類繼承。
class Foo {
static classMethod() {
return 'hello';
}
}
class Bar extends Foo {
}
Bar.classMethod(); // 'hello'
上面程式碼中,父類Foo有一個靜態方法,子類Bar可以呼叫這個方法。
靜態方法也是可以從super物件上呼叫的。
class Foo {
static classMethod() {
return 'hello';
}
}
class Bar extends Foo {
static classMethod() {
return super.classMethod() + ', too';
}
}
Bar.classMethod();
new.target屬性
new是從建構函式生成例項的命令。ES6為new命令引入了一個new.target屬性,(在建構函式中)返回new命令作用於的那個建構函式。如果建構函式不是通過new命令呼叫的,new.target會返回undefined,因此這個屬性可以用來確定建構函式是怎麼呼叫的。
function Person(name) {
if (new.target !== undefined) {
this.name = name;
} else {
throw new Error('必須使用new生成例項');
}
}
// 另一種寫法
function Person(name) {
if (new.target === Person) {
this.name = name;
} else {
throw new Error('必須使用new生成例項');
}
}
var person = new Person('張三'); // 正確
var notAPerson = Person.call(person, '張三'); // 報錯
上面程式碼確保建構函式只能通過new命令呼叫。
- Class內部呼叫new.target,返回當前Class。
- 子類繼承父類時,new.target會返回子類。
修飾器
修飾器(Decorator)是一個表示式,用來修改類的行為。
修飾器函式可以接受三個引數,依次是目標函式、屬性名和該屬性的描述物件。後兩個引數可省略。上面程式碼中,testable函式的引數target,就是所要修飾的物件。如果希望修飾器的行為,能夠根據目標物件的不同而不同,就要在外面再封裝一層函式。
function testable(isTestable) {
return function(target) {
target.isTestable = isTestable;
}
}
@testable(true) class MyTestableClass () {}
document.write(MyTestableClass.isTestable) // true
@testable(false) class MyClass () {}
document.write(MyClass.isTestable) // false
如果想要為類的例項新增方法,可以在修飾器函式中,為目標類的prototype屬性新增方法。
function testable(target) {
target.prototype.isTestable = true;
}
@testable
class MyTestableClass () {}
let obj = new MyClass();
document.write(obj.isTestable) // true
export命令
模組功能主要由兩個命令構成:export和import。
export命令用於使用者自定義模組,規定對外介面;
- import命令用於輸入其他模組提供的功能,同時創造名稱空間(namespace),防止函式名衝突。
- ES6允許將獨立的JS檔案作為模組,允許一個JavaScript指令碼檔案呼叫另一個指令碼檔案。
現有profile.js檔案,儲存了使用者資訊。ES6將其視為一個模組,裡面用export命令對外部輸出了三個變數。
// profile.js
var firstName = 'Michael';
var lastName = 'Jackson';
var year = 1958;
export {firstName, lastName, year};
import命令
使用export命令定義了模組的對外介面以後,其他JS檔案就可以通過import命令載入這個模組(檔案)。
// main.js
import {firstName, lastName, year} from './profile';
function sfirsetHeader(element) {
element.textContent = firstName + ' ' + lastName;
}
上面程式碼屬於另一個檔案main.js,import命令就用於載入profile.js檔案,並從中輸入變數。import命令接受一個物件(用大括號表示),裡面指定要從其他模組匯入的變數名。大括號裡面的變數名,必須與被匯入模組(profile.js)對外介面的名稱相同。
如果想為輸入的變數重新取一個名字,import語句中要使用as關鍵字,將輸入的變數重新命名。
import { lastName as surname } from './profile';
ES6支援多重載入,即所載入的模組中又載入其他模組。
模組的整體輸入
export命令除了輸出變數,還可以輸出方法或類(class)。下面是一個circle.js檔案,它輸出兩個方法area和circumference。
// circle.js
export function area(radius) {
return Math.PI * radius * radius;
}
export function circumference(radius) {
return 2 * Math.PI * radius;
}
然後,main.js輸入circlek.js模組。
// main.js
import { area, circumference } from 'circle';
document.write("圓面積:" + area(4));
document.write("圓周長:" + circumference(14));
上面寫法是逐一指定要輸入的方法。另一種寫法是整體輸入。
import * as circle from 'circle';
document.write("圓面積:" + circle.area(4));
document.write("圓周長:" + circle.circumference(14));
module命令
module命令可以取代import語句,達到整體輸入模組的作用。
// main.js
module circle from 'circle';
document.write("圓面積:" + circle.area(4));
document.write("圓周長:" + circle.circumference(14));
module命令後面跟一個變數,表示輸入的模組定義在該變數上。
export default命令
為載入模組指定預設輸出,使用export default命令。
// export-default.js
export default function () {
document.write('foo');
}
上面程式碼是一個模組檔案export-default.js,它的預設輸出是一個函式。
其他模組載入該模組時,import命令可以為該匿名函式指定任意名字。
// import-default.js
import customName from './export-default';
customName(); // 'foo'
上面程式碼的import命令,可以用任意名稱指向export-default.js輸出的方法。需要注意的是,這時import命令後面,不使用大括號。
模組的繼承
模組之間也可以繼承。
假設有一個circleplus模組,繼承了circle模組。
// circleplus.js
export * from 'circle';
export var e = 2.71828182846;
export default function(x) {
return Math.exp(x);
}
上面程式碼中的“export *”,表示輸出circle模組的所有屬性和方法,export default命令定義模組的預設方法。
這時,也可以將circle的屬性或方法,改名後再輸出。
// circleplus.js
export { area as circleArea } from 'circle';
上面程式碼表示,只輸出circle模組的area方法,且將其改名為circleArea。
載入上面模組的寫法如下。
// main.js
module math from "circleplus";
import exp from "circleplus";
document.write(exp(math.pi));
上面程式碼中的"import exp"表示,將circleplus模組的預設方法載入為exp方法。
對應的互動式免費學習課程在http://www.hubwiz.com/course/5594e91ac086935f4a6fb8ef/
相關文章
- ECMAScript 6:更好的 Unicode 支援Unicode
- Javascript——ES6( ECMAScript 6.0)語法JavaScript
- ECMAScript正規表示式6個最新特性
- ES6 (ECMAScript 6.0) 數值的介紹
- ECMAScript 6入門 - 變數的解構賦值變數賦值
- 重整旗鼓,2019自結前端面試小冊【ECMAScript 6】前端面試
- ECMAScript 2024 更新指南
- JavaScript ECMAScript版本介紹JavaScript
- [譯] ECMAScript 的 Observables 提案
- 【ECMAScript】睡眠、陣列洗牌陣列
- JavaScript(ECMAScript+BOM+DOM)JavaScript
- JavaScript與ECMAScript 區別JavaScript
- ECMAScript 2021 正式確認
- Python系列教程6Python
- leapftp教程,掌握leapftp教程只需6步FTP
- ECMAScript Decorators---裝飾器
- JavaScript: ECMAScript 2018(ES2018)JavaScript
- ECMAScript 2021主要新功能 – thenewstack
- Seastar 教程(三)AST
- Python教程-6模組Python
- ECMAScript5 Array新增方法
- [譯] ECMAScript 修飾器微指南
- 你知道什麼是ECMAScript嗎?
- CommonJS模組 和 ECMAScript模組JS
- 種草ECMAScript2021新特性
- IPv6入門教程
- ECMAScript5.1及其新增API簡介API
- ECMAScript 原始型別與引用型別型別
- 厲害了,ECMAScript 新提案:JSON模組JSON
- ECMASCRIPT 2021新功能程式碼演示案例
- 如何動態匯入ECMAScript模組
- leapftp 3.0.1使用教程,6步掌握leapftp 3.0.1使用教程FTP
- 兄弟連go教程(6)指標Go指標
- Primer Premier 6安裝使用教程REM
- NSIS 入門教程 (三)
- [譯] 瀏覽器中的 ECMAScript 模組瀏覽器
- 探索 ECMAScript 2023 中的新陣列方法陣列
- ECMAScript-淺拷貝和深拷貝
- ECMAScript-新的資料結構Map資料結構