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 屬性 一節