【es6】【Class的基本語法】

class類是一種概念,可以理解爲Java裏的class類。
它的數據類型是 function。
也可以完全看做是es5構造函數的另一種寫法。
那它具體是怎麼語法形式呢?
語法:

class Dlfd {
  constructor (a,b) {
    this.x = a;// 此處的兩個this默認指向類的實例
    this.y = b;
  }
  toString () {
    return '(' + this.x + ',' + this.y + ')';
  }
}

const xlfd = new Dlfd ('xlfd','lxh');
xlfd.x = "xlfd";
xlfd.toString();// "(xlfd,lxh)"
Dlfd === Dlfd.prototype.constructor;
// true 證明指向是構造函數(Dlfd類指向自己中的構造函數constructor)

讓我們看看es5中,生成實例對象的傳統方法------構造函數

function Dlfd (a,b) {
  this.x = a;// 此處也是指向實例對象
  this.y = b;
}
Dlfd.prototype.toString = function () {
  return '(' + this.x + ',' + this.y ')';
}

var xlfd = new Dlfd ("xlfd","lxh");
xlfd.x = "xlfd";
xlfd.toString ();// "(xlfd,lxh)"

可以看出,es5的構造函數Dlfd,對應的是es6中Dlfd類的構造方法constructor。
還有一種實際編程中能用到的寫法:

let functionName = 'xlfd';
class asd {
  constructor () {
    // ...
  }
  [functionName] () {
    // ...
  }
}

constructor 方法
一個類中必有constructor方法,一種是顯示定義了(改寫默認的)的,一種是沒有顯示定義時,會默認添加一個空的constructor方法。
上文中說過,constructor中的this默認指向是實例對象,除了這個,constructor方法還默認返回實例對象(this)。但是可以修改它的默認返回爲另一個對象

class Daht {
  constructor () {
    return Object.create(null);// 表示返回一個沒有繼承任何原型方法的新創對象。
  }
}

類的實例對象
實例的屬性除非顯示定義在其本身(定義在this對象上,this.case),否則都是定義在原型上(class上)。

class Dlfd {
  constructor (a,b) {
    this.x = a;// 此處的兩個this默認指向類的實例
    this.y = b;
  }
  toString () {
    return '(' + this.x + ',' + this.y + ')';
  }
}
const xlfd = new Dlfd ('xlfd','lxh');
xlfd.hasOwnProperty('toString');// false
xlfd._proto_.hasOwnProperty('toString');// true

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

const jh = new Dlfd();
const gq = new Dlfd();
jh._proto_ === gq._proto_
// true 都是Dlfd.prototype

在實際編程中可利用這一特性,爲類Dlfd添加方法

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

p1._proto_.printName = function () { 
  return 'Oops' 
};// p1的原型上添加了一個printName方法

p1.printName() // "Oops"
p2.printName() // "Oops" 隨即在p2上也能訪問(繼承到了)到該方法

var p3 = new Point(4,2);
p3.printName() // "Oops" // 新實例p3也繼承到了該方法

Class 表達式
類還可以用表達式的形式定義。

const Dxlfd = class Dxh {
  getClassName () {
    return Dxh.name;
}
};

類的名字是Dxlfd不是Dxh,,當然咯,如果這個Dxh在類的內部沒用到的話,可以省略。
還有一種應用形式:

let Cxlfd = new class {
  constructor (newname) {
    this.name = newname;
}
getName () {
  console.log(this.name);  
}
}('xlfd');

Cxlfd.getName()// "xlfd"

不存在變量提升

var ss = new Dlfd(1,2);
function Dlfd (a,b) {
  this.x = a;// 此處也是指向實例對象
  this.y = b;
}
console.log(ss.x);// 1

上面代碼是es5的變量提升現象,構造函數會提升到代碼頭部

但是es6中的類不存在變量提升:

var ss = new Dlfd(1,2); //ReferenceError: Dlfd is not defined
class Dlfd {
constructor (a,b) {
  this.x = a;// 此處也是指向實例對象
  this.y = b;
}
}
console.log(ss.x);

this的指向
類的方法內部如果含有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

單獨提出來使用該方法時,this會指向該方法運行時所在的環境,如這個運行環境沒有print方法,就會報錯
解決這種情況有三種方法:

// 一,在類的構造函數中綁定this
// 二,在類的構造函數中使用箭頭函數
// 三,Proxy
// 參考 http://es6.ruanyifeng.com/#docs/class  this指向一節

Class 的取值函數和存值函數
定義了一個類後,想在其中取值和存值,如何做到呢?
可以在類的內部和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 的靜態方法
上面可以看出,類中的所有方法都會被實例繼承。
如果在一個方法前面加上static關鍵字,就表示該方法不會被實例繼承,而是直接通過類來調用,這個被加了static關鍵字的函數就是“靜態方法”。

class Wlfd {
  static xlfd () {
    console.log('i`m');
    return 'lxh';
}
}
Wlfd.xlfd()// "i`m"
const as = new Wlfd();
as.xlfd()// TypeError: as.xlfd is not a function

靜態函數中的this指向這個類,不是指向實例。

class Wlfd {
  static xlfd () {
    this.getName();// 指向的是類
}
  static getName () {
    console.log('lxh');
}
  getName () {// 靜態方法和非靜態方法可以重名
    console.log('not xlfd');
}
}

Wlfd.getName()// "lxh"

一個類繼承另一個類的語法和Java中類的繼承相似----extends

class Xlfd {
  static getName () {
    console.log('xlfd');
}
  getName () {
    console.log('lxh');
}
}
// 父類的靜態方法,可以被子類繼承
class Child_xlfd extends Xlfd {
  static Name () {
    super.getName();// 靜態方法也是可以從super對象上調用的,下面的Child_xlfd.Name()會輸出“xlfd”
}
}

Child_xlfd.getName()// "xlfd"
const vae = new Child_xlfd();
vae.getName()// "lxh"
Child_xlfd.Name()// "xlfd"

類的靜態方法有了,要是想在類上添加靜態屬性,應該這麼寫:
目前沒看出實際上的意義

class Xlfd {
}

Xlfd.x = 1;
console.log(Xlfd.x);// 輸出 1

new.target 屬性
http://es6.ruanyifeng.com/#docs/class 中的 new.target 屬性 一節

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