注:此篇文章是我參考阮一峰老師的[ECMAScript 6 入門]文章,自己記錄的筆記,詳細的內容請移步阮一峰老師的文章。
1. CLASS
在 ES6 的“類”上面繼續存在。事實上,類的所有方法都定義在類的prototype屬性上面。
class Point {
constructor() {
// ...
}
toString() {
// ...
}
toValue() {
// ...
}
}
// 等同于
Point.prototype = {
constructor() {},
toString() {},
toValue() {},
};
由于類的方法都定義在prototype對象上面,所以類的新方法可以添加在prototype對象上面 Object.assign
方法可以很方便地一次向類添加多個方法。
class Point {
constructor(){
// ...
}
}
Object.assign(Point.prototype, {
toString(){},
toValue(){}
});
prototype對象的constructor屬性,直接指向“類”的本身,這與 ES5 的行為是一致的。
Point.prototype.constructor === Point //
- contructor
constructor方法是類的默認方法,通過new命令生成對象實例時,自動調用該方法。一個類必須有constructor方法,如果沒有顯式定義,一個空的constructor方法會被默認添加。
- 類的實例
實例的屬性除非顯式定義在其本身(即定義在this對象上),否則都是定義在原型上(即定義在class上)
class people {
constructor(x,y){
this.x =x ;
this.y =y
}
sayNum(){
console.log(this.x)
}
}
let wt =new people(1,2);
wt.sayNum()
console.log(wt.hasOwnProperty('x')) //true
function hasPrototypeProperty(obj,pro){
return !obj.hasOwnProperty(pro)
}
console.log(hasPrototypeProperty(wt,'sayNum')) //true
Class 的取值函數(getter)和存值函數(setter)
與 ES5 一樣,在“類”的內部可以使用get和set關鍵字,對某個屬性設置存值函數和取值函數,攔截該屬性的存取行為。
class MyClass {
constructor() {
// ...
}
get prop() {
return 'getter';
}
set prop(value) {
console.log('setter: '+value);
}
}
let inst = new MyClass();
inst.prop = 123;
// setter: 123
inst.prop
// 'getter'
- CLASS繼承
class people {
constructor(x,y){
this.x =x ;
this.y =y
}
sayNum(){
console.log(this.x)
}
}
class student extends people {
constructor(x,y){
super(x,y) //會調用父類的構造函數
}
saydNum(){
super.sayNum()
}
}
let mj=new student(101,102)
mj.saydNum()
super
它在這里表示父類的構造函數,用來新建父類的this對象。
子類必須在constructor方法中調用super方法,否則新建實例時會報錯。這是因為子類沒有自己的this對象,而是繼承父類的this對象,然后對其進行加工。如果不調用super方法,子類就得不到this對象。
另一個需要注意的地方是,在子類的構造函數中,只有調用super之后,才可以使用this關鍵字,否則會報錯。這是因為子類實例的構建,是基于對父類實例加工,只有super方法才能返回父類實例。
- Object.getPrototypeOf()
Object.getPrototypeOf
方法可以用來從子類上獲取父類。
Object.getPrototypeOf(ColorPoint) === Point
// true
因此,可以使用這個方法判斷,一個類是否繼承了另一個類
- super
super
這個關鍵字,既可以當作函數使用,也可以當作對象使用。在這兩種情況下,它的用法完全不同。
第一種情況,super作為函數調用時,代表父類的構造函數。ES6 要求,子類的構造函數必須執行一次super函數。
class A {}
class B extends A {
constructor() {
super();
}
}
上面代碼中,子類B的構造函數之中的super(),代表調用父類的構造函數。這是必須的,否則 JavaScript 引擎會報錯。
注意,super雖然代表了父類A的構造函數,但是返回的是子類B的實例,即super內部的this指的是B,因此super()在這里相當于A.prototype.constructor.call(this)。
第二種情況,super作為對象時,在普通方法中,指向父類的原型對象;在靜態方法中,指向父類。
class A {
p() {
return 2;
}
}
class B extends A {
constructor() {
super();
console.log(super.p()); // 2
}
}
let b = new B();
這里需要注意,由于super指向父類的原型對象,所以定義在父類實例上的方法或屬性,是無法通過super調用的。
class A {
constructor() {
this.p = 2;
}
}
class B extends A {
get m() {
return super.p;
}
}
let b = new B();
b.m // undefined
上面代碼中,p是父類A實例的屬性,super.p就引用不到它。
如果屬性定義在父類的原型對象上,super就可以取到。
class A {}
A.prototype.x = 2;
class B extends A {
constructor() {
super();
console.log(super.x) // 2
}
}
let b = new B();
如果super作為對象,用在靜態方法之中,這時super將指向父類,而不是父類的原型對象。
class Parent {
static myMethod(msg) {
console.log('static', msg);
}
myMethod(msg) {
console.log('instance', msg);
}
}
class Child extends Parent {
static myMethod(msg) {
super.myMethod(msg);
}
myMethod(msg) {
super.myMethod(msg);
}
}
Child.myMethod(1); // static 1
var child = new Child();
child.myMethod(2); // instance 2