在上一篇文章裏我介紹了一下面向對象編程的概念,在最後終於喜出望外看到了ES6
提供了類的概念了。那這個類如何去用,是這篇文章的主題。ES6
給咱們提供了一個class
關鍵字。這個關鍵字跟之前的var
let
const
很像,它們都是用作聲明的,而class
就是用來聲明一個類的。javascript
class name [extends]{ //extends是用來繼承的,可選參數 //class body };
注意java
- class不能重複聲明(與let、const同樣)
- 類的本質仍是一個構造函數
class Div{ //類 constructor(x,y){ //構造函數 this.x=x; //共享屬性,放在constructor裏 this.y=y; }//注意這裏是沒有逗號的 move(){ //共享方法,這裏至關於在Div.prototye上添加方法 console.log('動起來'); } } console.dir(Div); //在控制檯裏看一下與ES5的面向對象程序有什麼不一樣
在ES5
裏面的面向對象,所謂的「類」與構造函數實際上是一個東西,也就是雙重角色。而到了ES6
裏面真正的類與構造函數如今是分離的,經過上面的代碼能夠看出來,這種寫法正是面向對象的正統寫法。同時,咱們在控制檯裏看到這個對象與ES5
的對象區別僅在於顯示的名字上多了一個class
關鍵字,以下圖:編程
下面我要詳細的對比一下ES5
與ES6
的面向對象有什麼區別,以及用這種方式寫出來的對象與ECMAScript
的內置對象有什麼區別,這樣作的目的能讓你清晰的明白麪向對象編程到底是一種什麼樣的形式。segmentfault
const [div1,div2]=[new Div(10,20),new Div(15,20)]; //這兩個對象是爲了對比他們身上的原型 div1.z=30; //給實例添加一個私有屬性 console.log( typeof Div, //function 構造函數(雖然說是類,但實質仍是構造函數) Div.prototype.constructor===Div, //true 類本質仍是構造函數(披着羊皮的狼) //Object.getPrototypeOf方法是用來取對象身上的原型,用它代替__proto__ Object.getPrototypeOf(div1)===Div.prototype, //true 實例的原型就是構造函數的原型 Object.getPrototypeOf(div1)===Object.getPrototypeOf(div2), //true 兩個實例的原型都同樣,指向構造函數的原型對象 div1 instanceof Div, //true div是它的實例 div1.constructor===Div, //true 實例的構造函數就是類 /* * 方法說明 * Object.getOwnPropertyNames()這個方法是用來獲取對象身上的全部屬性名 * hasOwnProperty()用來判斷某個屬性是對象自身的(true),仍是繼承自原型對象的(false) * Object.keys()返回對象全部可枚舉(遍歷)的屬性名 */ Object.getOwnPropertyNames(div1),//["x", "y", "z"] 實例本身的屬性 div1.hasOwnProperty('x'), //true 實例的屬性 div1.hasOwnProperty('move'), //false 這個方法是繼承而來的 Object.keys(Div.prototype) //[] 對象身上的方法都是不可枚舉的 ); //ES5定義的對象,身上的方法是能夠枚舉的 function Car(){} Car.prototype.drive=function(){ console.log('竄的老快了'); } console.log(Object.keys(Car.prototype)); //["drive"] 全部方法都是可枚舉的
從上面的代碼得出如下的結論函數
- 類的本質仍是構造函數,其實class就是個語法糖,它的內部仍是個構造函數
- class聲明的對象與ES5聲明的對象實質上同樣
- class聲明的對象,它身上的方法都不能被枚舉
const [d1,d2]=[new Date(),new Date()]; //聲明兩個內置對象實例 d1.x=10,d1.y=20,d1.z=30; //給實例添加三個私有屬性 console.log( typeof Date, //function Date.prototype.constructor===Date, //true Object.getPrototypeOf(d1)===Date.prototype, //true Object.getPrototypeOf(d1)===Object.getPrototypeOf(d1), //true d1 instanceof Date, //true d1.constructor===Date, //true Object.getOwnPropertyNames(d1), //["x", "y", "z"] d1.hasOwnProperty('x'), //true d1.hasOwnProperty('getDate'), //false 這個方法是繼承於Date對象的 Object.keys(Date.prototype), //內置對象身上的方法都是不可枚舉的 );
從上面的代碼得出如下的結論this
- 自定義對象就是咱們聲明的一個相似於內置對象的對象
- JavaScript的面向對象編程,實質是把某個功能寫成一個對象,而且這個對象是在模仿內置對象
class
聲明的對象一樣容許小夥伴們任性的添加屬性與方法,包括共享與私有的。spa
- 共享屬性放在
constructor
裏,共享方法放在大括號內- 私有屬性放在類身上,私有方法放在大括號內同時前面要加
static
關鍵字- 私有方法裏
this
指向類自己,其它方法裏的this
指向實例對象
class Bear{ constructor(){ this.name='熊大'; //共享屬性(放在constructor裏) } sleep(){ //共享方法(直接放在大括號裏) this.name='熊二'; //this指向實例,因此在這裏給this添加屬性仍是實例的屬性 console.log(`${this.name}愛睡覺`); } static gohome(){ //私有方法 //類會默認添加一個name屬性,值爲class後面的那個單詞 console.log(`${this.name}的家在森林`); //這裏的this並不會指向實例,而是指向類 } } //共享屬性與方法 const b1=new Bear(); console.log(b1.name); //熊大 b1.sleep(); //熊大愛睡覺 console.log(b1.name); //熊二 sleep裏從新定義了name屬性,因此在這就被改了 //私有屬性與方法 Bear.age=5; //在外面添加私有屬性 console.log(b1.age); //undefined 實例不具有 Bear.gohome(); //Bear的家在森林 //b1.goHome(); //報錯,它是私有方法
下篇文章會詳細介紹class
裏的繼承。prototype