ES5和ES6中Class類的相同與不同
先說結論,簡而言之ES5用function定義類,ES6用class定義類,class的本質是function,ES6中的類只是語法糖,它並沒有改變ES5下類實現的本質。
類的定義
ES5
// ES5函數來描寫類 // 聲明類 let Animal = function (type) { this.type = type // 定義實例方法 this.drink = function () { console.log('drink') } } // 定義原型方法 Animal.prototype.eat = function () { console.log('eat food') } // 實例化 let dog = new Animal('dog') let monkey = new Animal('monkey')
ES6
// ES6 class // class的本質是ES5用原型鏈聲明類的語法糖 class Animal { constructor (type) { this.type = type } eat () { console.log('eat food') } } let dog = new Animal('dog') let monkey = new Animal('monkey')
ES6類中的set和get方法
- set用於設置屬性(無返回值)
- get用於讀取屬性(有返回值)
let _age = 4 class Animal { constructor (type) { this.type = type } get age () { return _age } set age (val) { this.realage = val } eat () { console.log('eat food') } } let dog = new Animal('dog') console.log(dog.age) // 4 dog.age = 5 // 未生效 get定義的為只讀屬性 console.log(dog.age) // 4 console.log(dog.realage) // 5
ES5類中的 實例方法&原型方法&靜態方法
-
實例方法只有實例可以調用
-
實例方法可以調用靜態方法,不能調用原型方法
-
原型方法可以被實例和構造函數訪問到
-
原型方法只可以調用靜態方法
-
靜態方法只有構造函數可以調用
ES5中定義三種方法及調用關系
let Animal = function (type) { this.type = type // 實例方法 this.drink = function () { // 實例方法可調用類的靜態方法 Animal.walk() console.log('drink') } } // 原型方法 Animal.prototype.eat = function () { // 原型方法可調用類的靜態方法 Animal.walk() console.log('eat food') } // 靜態方法 Animal.walk = function () { console.log('walking') } let dog = new Animal('dog') dog.drink() // walking drink dog.eat() // walking eat food Animal.walk() // walking靜態方法只能由<類自身&實例方法&原型方法>調用,實例對象無法調用 // dog.walk() // dog.walk is not a function 實例對象無法調用靜態方法
ES6類中的 實例方法&原型方法&靜態方法
-
實例方法=原型方法 類中直接定義的實例方法默認就是ES5中的原型方法(語法糖)
-
靜態方法用static前綴定義
-
靜態方法只有構造函數可以調用,原型方法是實例和構造函數都可以調用,是共享的方法。
class Animal { constructor (type) { this.type = type } // 定義實例對象的方法 eat () { // 使用靜態方法,以類形式訪問,而非this訪問 Animal.walk() console.log('eat food') console.log(this.type) // 類的例實例對象的方法可以獲取到實例對象的信息,輸出dog } // static 定義類的靜態方法 static walk () { console.log('walking') console.log(this.type) // 類的靜態方法無法獲取到實例對象的信息,輸出undefined } } let dog = new Animal('dog') dog.eat() // walking ; undefined ; eat food ; dog Animal.walk() // walking ; undefined ; dog.walk() // dog.walk is not a function // 得出結論:需要訪問實例對象的信息時用實例對象的方法,否則使用static靜態方法 // 實例方法就是只有實例可以調用,靜態方法只有構造函數可以調用,原型方法是實例和構造函數都可以調用,是共享的方法。
ES5 子類
-
.call方法指向父類
-
設置原型鏈指向相同
let Animal = function (type) { this.type = type // 實例方法 this.drink = function () { // 實例方法可調用類的靜態方法 Animal.walk() console.log('drink') } } // 原型方法 Animal.prototype.eat = function () { // 原型方法可調用類的靜態方法 Animal.walk() console.log('eat food') } // 靜態方法 Animal.walk = function () { console.log('walking') } let Dog = function () { // 初始化父類的構造函數,call的作用是改變this指向dog的實例 Animal.call(this, 'dog') this.run = function () { console.log('run') } } // 兩個原型鏈指向相同,子類才可以用父類的方法 Dog.prototype = Animal.prototype let dog = new Animal('dog') dog.eat() // 實例對象能調用類定義在原型上的實例對象的方法 // dog.walk() // 實例對象不能調用類的靜態方法 let realdog = new Dog('realdog') realdog.eat() realdog.run()
ES6 子類
-
extends定義子類,super指向父類的原型對象,可以調用父類的屬性和方法。
class Animal { constructor (type, age) { this.type = type this.age = age } detail () { console.log(this.type + ' ' + this.age) } } class Dog extends Animal { // 定義子類的構造函數 constructor (type, age, sex) { // super()要和父類的constructor一致 // super關鍵字表示調用父類的構造方法,也就是父類constructor中的內容 super(type, age) this.sex = sex } ndetail () { console.log(this.type + ' ' + this.age + ' ' + this.sex) } } // let cat = new Animal('cat', 20) // cat.detail() let dog = new Dog('dog', 5, 'gong') dog.ndetail()