ES6中class是基於原型的繼承的語法糖,提供更加清晰的語法來建立對象和原型。
es5 聲明一個構造函數:javascript
function Student(name, age) { this.name = name; this.age = age; } Student.prototype.getInfo = function() { return '{name:' + this.name + ',age:' + this.age + '}'; } Student.prototype.setInfo = function(name, age) { this.name = name; this.age = age; } var p = new Student('nico', 1); p.getInfo(); //{name:nico,age:1} p.setInfo('siip', 10); p.getInfo(); //{name:siip,10}
es6 聲明一個類:java
class Student { constructor(name, age) { this.name = name; this.age = age; } getInfo() { return `{name:${this.name},age:${this.age}}`; } setInfo(name, age) { this.name = name; this.age = age; } } let p = new Student('nico', 1); p.setInfo('siip', 10); p.getInfo();//{name:siip,10}
以上二者相比之下,很能夠看出,es6類函數比es5構造函數,代碼量更少,而且結構層次更加簡潔明瞭。es6
有些地方須要注意的是:express
constructorbabel
constructor是默認的方法,就算在聲明類函數時沒有寫constructor方法,在實例化時會自動添加上一個空的constructor函數
class Student { constructor() { this.desc = 'test'; } }
經過babel轉碼:this
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var Student = function Student() { _classCallCheck(this, Student);//類不能直接被調用,只能經過new實例化 this.desc = 'test'; };
constructor方法指向自身,在一個類中只能有一個名爲 「constructor」 的特殊方法。es5
Student === Student.prototype.constructor;//true
staticprototype
簡述:顧名思義這是一個靜態方法,就是不須要實例化類就能夠調用的方法, 實例化對象不能繼承靜態方法。code
class Student { constructor(name, age) { this.name = name; this.age = age; } static ageFilter(...args) { let stuAge = args; let arr = []; for (let i = 0; i < stuAge.length; i++) { if (stuAge[i].age > 12) { arr.push(stuAge[i]) } } return arr; } getInfo() { return `{name:${this.name},age:${this.age}}`; } setInfo(name, age) { this.name = name; this.age = age; } } Student.ageFilter({ name: 'a', age: 1 }, { name: 'b', age: 14 });//{name: "a", age: 14}
靜態函數的this指向類函數自身,當this沒有指明被誰調用時,this爲undefined
咱們將上面代碼用babel編譯,從結果上看:
var _createClass = function() { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function(Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();
從代碼能夠看出,靜態方法與類函數方法的區別是:當用Object.defineProperty去定義對象屬性時傳入的對象不一樣,一個傳入的是構造函數的原型,另外一個是傳入構造函數。
es6當前還不支持靜態屬性
extends
關鍵字在類聲明或類表達式中用於建立一個類做爲另外一個類的一個子類
class Student { constructor(name = null, age = null) { this.name = name; this.age = age; } getInfo() { return `{name:${this.name},age:${this.age}}`; } setInfo(name, age) { this.name = name; this.age = age; } } class Citizen extends Student { constructor(name, age) { super(name, age); this.name = 123; } } let stu = new Citizen('siip', '25'); stu.getInfo(); //{name:siip,age:25}
能夠看到子類能夠調用父類上的方法和屬性,當使用extends繼承父類時,子類constructor和super和被默認添加上,而且在構造函數內,只有調用了super函數後才能使用this,不然會拋出ReferenceError錯誤
constructor() { this.name = 'xxx' super() }//ReferenceError
super
下面一個子類繼承父類的Math的方法:
function MathFns() { this.status = 'Father' } MathFns.prototype = Math; class Max extends MathFns { constructor() { super(); } static base() { return super.max(); } } let m = new MathFns(); m; //{status: "Father"} m.max(1, 2);//2
咱們能夠經過babel編譯,嘗試去理解es6的繼承,
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }
這個封裝繼承函數,主要實現的功能是,子類原型指向父類,原型構造器指向自身,而後再經過隱式原型鏈指向父類函數,這樣子類被實例化後的對像就能使用父類原型鏈上的方法以及經過隱式原型鏈訪問到父類的屬性。
總的來看,es6的class類其實是基於原型鏈和繼承作的一層封裝,它的結構層次相對於es5原型鏈寫法更加清晰明瞭,代碼量更少。class類主要內容是構造函數、靜態方法、繼承。
構造函數
靜態方法
繼承