在es6中,咱們能夠用class
關鍵字來定義類,語法以下javascript
class Person { // 構造函數 constructor (name) { // 屬性初始化 this.name = name; } // 成員方法 sayName () { console.log(this.name); } // 靜態方法 static sayHi () { console.log("Hi~"); } }
其實本質仍是基於javascript原型鏈機制開發的語法糖
,其中,本人對setter/getter進行一番研究,發現了很多坑。java
class Person { constructor (name, age) { this.name = name; this.age = age; } set name (name) { console.log("setter"); this.name = name; } get name () { console.log("getter"); return this.name; } } var p = new Person("zhang", 25);
很快,咱們就會發現代碼報錯了es6
這是由於,在構造函數中執行this.name=name
的時候,就會去調用set name
,在set name方法中,咱們又執行this.name = name
,進行無限遞歸,最後致使棧溢出(RangeError)。函數
咱們稍做修改,讓這個代碼能夠正常執行,達到咱們想要的效果。this
class Person { constructor (name, age) { this.name = name; this.age = age; } set name (name) { console.log("setter"); this._name = name; } get name () { console.log("getter"); return this._name; } // 加一個成員方法 sayName () { console.log(this.name); } } var p = new Person("zhang", 25); p.sayName();
執行結果爲spa
到這裏就能夠明白了,原來只要this.name中的屬性名和set name/get name後面的name一致,對this.name就會調用setter/getter,也就是說setter/getter是hook函數
,而真實的存儲變量是_name
,咱們能夠在代碼中直接獲取它。code
class Person { constructor (name, age) { this.name = name; this.age = age; } set name (name) { console.log("setter"); this._name = name; } get name () { console.log("getter"); return this._name; } // 加一個成員方法 sayName () { console.log(this.name); } } var p = new Person("zhang", 25); console.log(p._name); // "zhang"
執行結果爲blog
注意到結果並無執行getter,由於咱們直接訪問了p._name
,而不是p.name
遞歸
當一個屬性只有getter沒有setter的時候,咱們是沒法進行賦值操做的(第一次初始化也不行),這一點也是至關地坑
。例如圖片
class Person { constructor (name) { this.name = name; } // 只有getter get name () { console.log("getter"); return this.name; } } var p = new Person("zhang");
執行結果爲
當沒有getter和setter時,就能夠正常讀寫屬性