1. 程式人生 > 其它 >es6中class的理解

es6中class的理解

  傳統的javascript中只有物件,沒有類的概念。它是基於原型的面嚮物件語言。原型物件特點就是將自身的屬性共享給新物件。這樣的寫法相對於其它傳統面嚮物件語言來講,很有一種獨樹一幟的感腳!非常容易讓人困惑!
如果要生成一個物件例項,需要先定義一個建構函式,然後通過new操作符來完成。建構函式示例:
 1 //函式名和例項化構造名相同且大寫(非強制,但這麼寫有助於區分建構函式和普通函式)
 2 function Person(name,age) {
 3     this.name = name;
 4     this.age=age;
 5 }
 6 Person.prototype.say = function
(){ 7 return "我的名字叫" + this.name+"今年"+this.age+"歲了"; 8 } 9 var obj=new Person("laotie",88);//通過建構函式建立物件,必須使用new 運算子 10 console.log(obj.say());//我的名字叫laotie今年88歲了

  建構函式生成例項的執行過程:

  1. 當使用了建構函式,並且new 建構函式(),後臺會隱式執行newObject()建立物件;
  2. 將建構函式的作用域給新物件,(即newObject()創建出的物件),而函式體內的this就代表newObject()出來的物件。
  3. 執行建構函式的程式碼。
  4. 返回新物件(後臺直接返回);

  ES6引入了Class(類)這個概念,通過class關鍵字可以定義類。該關鍵字的出現使得其在物件寫法上更加清晰,更像是一種面向物件的語言。如果將之前的程式碼改為ES6的寫法就會是這個樣子:

 1 class Person{//定義了一個名字為Person的類
 2     constructor(name,age){//constructor是一個構造方法,用來接收引數
 3         this.name = name;//this代表的是例項物件
 4         this.age=age;
 5     }
 6     say(){//這是一個類的方法,注意千萬不要加上function
7 return "我的名字叫" + this.name+"今年"+this.age+"歲了"; 8 } 9 } 10 var obj=new Person("laotie",88); 11 console.log(obj.say());//我的名字叫laotie今年88歲了

  注意:

  1.在類中宣告方法的時候,千萬不要給該方法加上function關鍵字
  2.方法之間不要用逗號分隔,否則會報錯

 由下面程式碼可以看出類實質上就是一個函式。類自身指向的就是建構函式。所以可以認為ES6中的類其實就是建構函式的另外一種寫法!
1 console.log(typeof Person);//function
2 console.log(Person===Person.prototype.constructor);//true

  類的所有方法都定義在類的prototype屬性上



1 Person.prototype.say=function(){//定義與類中相同名字的方法。成功實現了覆蓋!
2     return "我是來證明的,你叫" + this.name+"今年"+this.age+"歲了";
3 }
4 var obj=new Person("laotie",88);
5 console.log(obj.say());//我是來證明的,你叫laotie今年88歲了

  當然也可以通過prototype屬性對類新增方法

1 Person.prototype.addFn=function(){
2     return "我是通過prototype新增加的方法,名字叫addFn";
3 }
4 var obj=new Person("laotie",88);
5 console.log(obj.addFn());//我是通過prototype新增加的方法,名字叫addFn

  還可以通過Object.assign方法來為物件動態增加方法

 1 Object.assign(Person.prototype,{
 2     getName:function(){
 3         return this.name;
 4     },
 5     getAge:function(){
 6         return this.age;
 7     }
 8 })
 9 var obj=new Person("laotie",88);
10 console.log(obj.getName());//laotie
11 console.log(obj.getAge());//88

  constructor方法是類的建構函式的預設方法,通過new命令生成物件例項時,自動呼叫該方法。



1 class Box{
2     constructor(){
3         console.log("啦啦啦,今天天氣好晴朗");//當例項化物件時該行程式碼會執行。
4     }
5 }
6 var obj=new Box();


  constructor方法如果沒有顯式定義,會隱式生成一個constructor方法。所以即使你沒有新增建構函式,建構函式也是存在的。constructor方法預設返回例項物件this,但是也可以指定constructor方法返回一個全新的物件,讓返回的例項物件不是該類的例項。

 1 class Box{
 2     constructor(num1,num2){
 3         this.num1 = num1;
 4         this.num2=num2;
 5     }
 6     sum(){
 7         return num1+num2;
 8     }
 9 }
10 var box=new Box(12,88);
11 console.log(box.hasOwnProperty("num1"));//true
12 console.log(box.hasOwnProperty("num2"));//true
13 console.log(box.hasOwnProperty("sum"));//false
14 console.log("num1" in box);//true
15 console.log("num2" in box);//true
16 console.log("sum" in box);//true
17 console.log("say" in box);//false

  類的所有例項共享一個原型物件,它們的原型都是Person.prototype,所以proto屬性是相等的

 1 class Box{
 2     constructor(num1,num2){
 3         this.num1 = num1;
 4         this.num2=num2;
 5     }
 6     sum(){
 7         return num1+num2;
 8     }
 9 }
10 //box1與box2都是Box的例項。它們的__proto__都指向Box的prototype
11 var box1=new Box(12,88);
12 var box2=new Box(40,60);
13 console.log(box1.__proto__===box2.__proto__);//true

  由此,也可以通過proto來為類增加方法。使用例項的proto屬性改寫原型,會改變Class的原始定義,影響到所有例項,所以不推薦使用!

 1 class Box{
 2     constructor(num1,num2){
 3         this.num1 = num1;
 4         this.num2=num2;
 5     }
 6     sum(){
 7         return num1+num2;
 8     }
 9 }
10 var box1=new Box(12,88);
11 var box2=new Box(40,60);
12 box1.__proto__.sub=function(){
13     return this.num2-this.num1;
14 }
15 console.log(box1.sub());//76
16 console.log(box2.sub());//20

  class不存在變數提升,所以需要先定義再使用。因為ES6不會把類的宣告提升到程式碼頭部,但是ES5就不一樣,ES5存在變數提升,可以先使用,然後再定義。

 1 //ES5可以先使用再定義,存在變數提升
 2 new A();
 3 function A(){
 4 
 5 }
 6 //ES6不能先使用再定義,不存在變數提升 會報錯
 7 new B();//B is not defined
 8 class B{
 9 
10 }

本文來自部落格園,作者:冰中焱,轉載請註明原文連結:https://www.cnblogs.com/Blod/p/15801399.html