Class 的基本語法

class Point {
  constructor(x, y) {
    this.x = x;
    this.y = y;
  }

  toString() {
    return '(' + this.x + ', ' + this.y + ')';
  }
}

 

面代碼定義了一個“類”,可以看到裏面有一個constructor方法,這就是構造方法,而this關鍵字則代表實例對象。也就是說,ES5 的構造函數Point,對應 ES6 的Point類的構造方法。

Point類除了構造方法,還定義了一個toString方法。注意,定義“類”的方法的時候,前面不需要加上function這個關鍵字,直接把函數定義放進去了就可以了。另外,方法之間不需要逗號分隔,加了會報錯。

constructor方法是類的默認方法,通過new命令生成對象實例時,自動調用該方法。一個類必須有constructor方法,如果沒有顯式定義,一個空的constructor方法會被默認添加。

constructor方法默認返回實例對象(即this),完全可以指定返回另外一個對象。

class Foo {
  constructor() {
    return Object.create(null);
  }
}

new Foo() instanceof Foo
// false

上面代碼中,constructor函數返回一個全新的對象,結果導致實例對象不是Foo類的實例。

類必須使用new調用,否則會報錯。這是它跟普通構造函數的一個主要區別,後者不用new也可以執行。

class Foo {
  constructor() {
    return Object.create(null);
  }
}

Foo()
// TypeError: Class constructor Foo cannot be invoked without 'new'

類的所有實例共享一個原型對象。

var p1 = new Point(2,3);
var p2 = new Point(3,2);

p1.__proto__ === p2.__proto__
//true

 在“類”的內部可以使用getset關鍵字,對某個屬性設置存值函數和取值函數,攔截該屬性的存取行爲。

 

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'

屬性表達式

類的屬性名,可以採用表達式。

let methodName = 'getArea';

class Square {
  constructor(length) {
    // ...
  }

  [methodName]() {
    // ...
  }
}

上面代碼中,Square類的方法名getArea,是從表達式得到的。

Class 表達式 § 

與函數一樣,類也可以使用表達式的形式定義。

const MyClass = class Me {
  getClassName() {
    return Me.name;
  }
};

上面代碼使用表達式定義了一個類。需要注意的是,這個類的名字是MyClass而不是MeMe只在 Class 的內部代碼可用,指代當前類。

let inst = new MyClass();
inst.getClassName() // Me
Me.name // ReferenceError: Me is not defined

上面代碼表示,Me只在 Class 內部有定義。

如果類的內部沒用到的話,可以省略Me,也就是可以寫成下面的形式。

const MyClass = class { /* ... */ };

採用 Class 表達式,可以寫出立即執行的 Class。

let person = new class {
  constructor(name) {
    this.name = name;
  }

  sayName() {
    console.log(this.name);
  }
}('張三');

person.sayName(); // "張三"

 name屬性

class Point {}
Point.name // "Point"

 

this 的指向

類的方法內部如果含有this,它默認指向類的實例。但是,必須非常小心,一旦單獨使用該方法,很可能報錯。

class Logger {
  printName(name = 'there') {
    this.print(`Hello ${name}`);
  }

  print(text) {
    console.log(text);
  }
}

const logger = new Logger();
const { printName } = logger;
printName(); // TypeError: Cannot read property 'print' of undefined

 

如果在一個方法前,加上static關鍵字,就表示該方法不會被實例繼承,而是直接通過類來調用,這就稱爲“靜態方法”。

class Foo {
  static classMethod() {
    return 'hello';
  }
}

Foo.classMethod() // 'hello'

var foo = new Foo();
foo.classMethod()
// TypeError: foo.classMethod is not a function

如果靜態方法包含this關鍵字,這個this指的是類,而不是實例。

class Foo {
  static bar() {
    this.baz();
  }
  static baz() {
    console.log('hello');
  }
  baz() {
    console.log('world');
  }
}

Foo.bar() // hello

上面代碼中,靜態方法bar調用了this.baz,這裏的this指的是Foo類,而不是Foo的實例,等同於調用Foo.baz。另外,從這個例子還可以看出,靜態方法可以與非靜態方法重名。

父類的靜態方法,可以被子類繼承。

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() // "hello, too"

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章