ES6 Class(类)的继承与常用方法
一、ES6 類的定義
ES5 構造函數的寫法:
function Point(x, y) {
this.x = x;
this.y = y;
}
ES6 引入了 Class(類),通過class關鍵字,可以定義類。
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
這里,ES6 的 Point 類的構造方法對應前面 ES5 的構造函數 Point,代碼中的constructor是構造方法。
關于 constructor
constructor是類的默認方法,通過new命令生成對象實例時,自動調用該方法。一個類必須有
constructor方法,如果沒有顯式定義,一個空的constructor方法會被默認添加:class Point { } // 等同于 class Point { constructor() {} }
二、ES6 類的實例
生成類的實例與 ES5 一樣,也是用new命令。
但構造函數的實例不用 new 也可以執行,而類必須用 new,否則會報錯:
class Point {
// ...
}
// 報錯
var point = Point(2, 3);
// 正確
var point = new Point(2, 3);
三、ES6 類的繼承
1、Object.getPrototypeOf()
Object.getPrototypeOf 方法可以用來從子類上獲取父類,判斷一個類是否繼承了另一個類
Object.getPrototypeOf(foo) === Foo // true
2、extends 關鍵字實現繼承
class Parent{
constructor(lastName='Liu'){
this.lastName=lastName;
}
}
class Child extends Parent{
constructor(lastName){
super(lastName);
}
}
console.log(new Child('Chen'));
// 輸出結果
3、super 關鍵字
① super 作為函數調用時,代表父類的構造函數(ES6 要求,子類的構造函數必須執行一次 super 函數,否則會報錯)
class A {}
class B extends A {
constructor() {
super();
}
}
注意,super 雖然代表了父類 A 的構造函數,但返回的是子類 B 的實例,即 super 內部的 this 指的是 B 的實例,因此 super() 在這里相當于 A.prototype.constructor.call(this)
class A {
constructor() {
console.log(new.target.name);
}
}
class B extends A {
constructor() {
super();
}
}
new A() // A
new B() // B
上面代碼中,new.target 指向當前正在執行的函數??梢钥吹?,在 super() 執行時,它指向的是子類 B 的構造函數,而不是父類 A 的構造函數。也就是說,super() 內部 的 this 指向的是子類 B
②super 作為對象時,在普通方法中指向父類的原型對象;在靜態方法中則指向父類
class A {
p() {
return 2;
}
}
class B extends A {
constructor() {
super();
console.log(super.p()); // 2
}
}
let b = new B();
上面代碼中,子類 B 當中的 super.p(),就是將 super 當作一個對象使用。這時,super 在普通方法之中,指向 A.prototype,所以 super.p() 就相當于 A.prototype.p()
注意,使用 super 的時必須顯式指定是作為函數、還是作為對象使用,否則會報錯
class A {}
class B extends A {
constructor() {
super();
console.log(super); // 報錯
}
}
上面代碼中,console.log(super) 當中的 super,無法看出是作為函數使用,還是作為對象使用,所以 JavaScript 引擎解析代碼的時候就會報錯
super 關鍵字擴展
① 類的繼承
② 類的重寫(覆蓋)
③ 類重寫后使用 super 關鍵字重新調用父類方法
四、getter 和 setter
與 ES5 一樣,在“類”的內部可以使用 get 和 set 關鍵字,對某個屬性設置取值函數和存值函數,攔截該屬性的存取行為
1、getter(取值函數)
class Parent{
constructor(name='Winnie'){
this.name=name;
}
get longName(){
return 'Liu'+this.name;
}
}
let getterName=new Parent();
console.log(getterName.longName); // LiuWinnie
2、setter(存值函數)
class Parent{
constructor(name='Winnie'){
this.name=name;
}
get longName(){
return 'Liu'+this.name;
}
set longName(value){
this.name=value;
}
}
let setterName=new Parent();
setterName.longName='Honey';
console.log(setterName.longName); // LiuHoney
五、public、private 和 protected
1、public
允許在類的內外被調用
2、private
只允許在類的內部被調用
3、protected
允許在類的內部及繼承的子類中調用
六、靜態方法/屬性
類相當于實例的原型,所有在類中定義的方法,都會被實例繼承。
但如果在一個方法前加上 static 關鍵字,則該方法不會被實例繼承,而是直接通過類來調用,這種方法稱為靜態方法。
1、靜態方法:使用 static 關鍵字
class Parent{
static tell(){
console.log('hello');
}
tell(){
console.log('world');
}
}
Parent.tell(); // hello
以上代碼還可以看出靜態方法可以與非靜態方法重名
2、靜態屬性:直接用 .屬性名
class Parent {
}
Parent.lastName = 'Liu';
console.log(Parent.lastName); // Liu
上面代碼為 Parent 類定義了一個靜態屬性 lastName
七、name 屬性
由于本質上,ES6 的類只是 ES5 的構造函數的一層包裝,所以函數的許多特性都被 Class 繼承,包括 name 屬性
class Point {}
Point.name // "Point"
name 屬性總是返回緊跟在 class 關鍵字后面的類名
let foo = class Foo {
constructor(){
this.name = 'Leo'
}
}
let child = new foo();
console.log(foo.name); // Foo
八、new.target 屬性
new 是從構造函數生成實例對象的命令。ES6 為 new 命令引入了一個 new.target 屬性,該屬性一般用在構造函數之中,返回 new 命令作用于的那個構造函數。如果構造函數不是通過 new 命令或 Reflect.construct() 調用的,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 命令調用
需要注意的是,子類繼承父類時,new.target 會返回子類
總結
以上是生活随笔為你收集整理的ES6 Class(类)的继承与常用方法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: swift解析html数据类型,ios-
- 下一篇: 更该clover软件图标(任务栏显示)