ES6引入了Class(類)這個概念,作為對象的模板,通過class關鍵字,可以定義類。基本上,ES6的class可以看作只是一個語法糖,它的絕大部分功能,ES5都可以做到,新的class寫法只是讓對象原型的寫法更加清晰、更像面向對象編程的語法而已。 那麼如何掌握類這項技能,讓我來陪大家一起學習: ...
ES6引入了Class(類)這個概念,作為對象的模板,通過class關鍵字,可以定義類。基本上,ES6的class可以看作只是一個語法糖,它的絕大部分功能,ES5都可以做到,新的class寫法只是讓對象原型的寫法更加清晰、更像面向對象編程的語法而已。
那麼如何掌握類這項技能,讓我來陪大家一起學習:
1.super關鍵字
super用在調用的時候有兩種情況:
第一種情況,super作為函數調用時,代表父類的構造函數。
第二種情況,super作為對象時,在普通方法中,指向父類的原型對象;在靜態方法中,指向父類。
class Person { constructor (name) { this.name = name; } height(){ console.log(1); } static weight(){ console.log(2); } } class Student extends Person { constructor (name, age) { super(); //代表父類的構造函數 this.age = age; } height(){ super.height(); //指向父類的原型對象 } static weight(){ super.weight(); //指向父類 } }
如果子類調用constructor,那麼子類必須在constructor方法中調用super方法,否則新建實例時會報錯。這是因為子類沒有自己的this對象,而是繼承父類的this對象,然後對其進行加工。如果不調用super方法,子類就得不到this對象。
總結下:
super 關鍵字用於調用一個對象的父對象上的函數。
super.prop 和 super[expr] 表達式在類 和 對象字面量 任何 方法定義 中都是有效的。
在構造函數中使用時,super關鍵字單獨出現,必須在可以使用this關鍵字之前使用。此關鍵字也可用於調用父對象上的函數。
2.static關鍵字
類相當於實例的原型, 所有在類中定義的方法, 都會被實例繼承。 如果在一個方法前, 加上static關鍵字, 就表示該方法不會被實例繼承, 而是直接通過類來調用, 這就稱為“ 靜態方法”。
靜態方法調用直接在類上進行,而在類的實例上不可被調用。
靜態方法通常用於創建 實用/工具 函數。
通過例子我們可以發現,靜態方法是通過類名直接調用的
從另一個靜態方法為了在同一個類的另一個靜態方法中調用一個靜態方法,你可以使用 this 關鍵字。
class StaticMethodCall { static staticMethod() { return 'Static method has been called'; } static anotherStaticMethod() { return this.staticMethod() + ' from another static method'; } } StaticMethodCall.staticMethod(); // 'Static method has been called' StaticMethodCall.anotherStaticMethod(); // 'Static method has been called from another static method'
從類的構造函數和其他方法靜態方法不能直接在非靜態方法中使用 this 關鍵字來訪問。你需要使用類名來調用它們:CLASSNAME.STATIC_METHOD_NAME() 或者將其作為構造函數的屬性來調用該方法: this.constructor.STATIC_METHOD_NAME().
class StaticMethodCall { constructor() { console.log(StaticMethodCall.staticMethod()); // 'static method has been called.' console.log(this.constructor.staticMethod()); // 'static method has been called.' } static staticMethod() { return 'static method has been called.'; } }
3.new.target 關鍵字
new.target屬性允許你檢測函數或構造方法是否通過是通過new運算符被調用的。在通過new運算符被初始化的函數或構造方法中,new.target返回一個指向構造方法或函數的引用。在普通的函數調用中,new.target 的值是undefined。
怎麼理解這段話,也就是說new.target的功能就是用來檢測函數的調用是不是通過 new 去創建一個新對象的,而且new.target返回的是一個指向函數的引用,也就是說我們能夠確定是哪個函數進行了new操作
class A { constructor() { console.log(new.target.name); } } class B extends A { constructor() { super(); } } var a = new A(); // logs "A" var b = new B(); // logs "B"
new.target 最大的作用就是讓構造器知道當前到底 new 的是哪個類。
延伸下。ES6之前怎麼實現這個功能?
var A = function A() { if(!(this instanceof A)) throw 'Constructor A requires "new"'; // ··· };
然而這依然可以通過 call 或 apply 來調用。比如:
var a = A.call(Object.create(A.prototype));
那麼用ES6就是下麵這樣操作了
var A = function A() { if(!new.target) throw 'Constructor A requires "new"'; // ··· };
4.constructor關鍵字
構造方法是創建和初始化使用類創建的一個對象的一種特殊方法。
class Square extends Polygon { constructor(length) { // 在這裡調用父類的"length",賦值給矩形的"width"和"height"。 super(length, length); // 註意:子類必須在constructor方法中調用super方法,否則新建實例時會報錯。 this.name = 'Square'; } get area() { return this.height * this.width; } set area(value) { this.area = value; } }
如果沒有顯式定義,會預設添加一個空的constructor方法。對於基類"Base classes",預設構造方法如下:
constructor() {}
對於派生類"Derived classes" ,預設構造方法如下:
constructor(...args) {
super(...args);
}