1、基本語法
經過class關鍵字,能夠定義類。該方法定義的原型對象跟ES5定義的沒有多少區別,只是用class的寫法能讓對象原型的定義更加清晰,更像面向對象編程的語法。
一、基本語法:編程
class Person{ constructor(name,age){ this.name = name; this.age = age; this.fun = ()=>console.log('constructor內的方法能夠被遍歷到哦') } say() { console.log(`My name is ${this.name}`) } } let p1 = new Person('Liane',18) p1.say() //My name is Liane //使用class建立的構造函數,全部的方法都會被定義在prototype屬性上面,所以是不可以被遍歷到的。 console.log(p1) //{name: 'Liane', age: 18,fun: f} for(let k in p1){ console.log(k) //name //age //fun } //因此,添加類的方法能夠使用Object.assign()方法,一次性向類添加多個方法 Object.assign(Person.prototype, { growUp(){ return ++this.age }, eat(food){ console.log(`${this.name}吃了${food}`) } }) p1.growUp() console.log(p1.age) //19 p1.eat('apple') //也可以使用Object.getPrototypeOf(obj)方法獲取obj的原型對象,再爲原型添加方法或屬性 Object.getPrototypeOf(p1) === Person.prototype //true
與ES5一致,實例對象p1的name、age、fun由於定義在this上,因此都是實例自身的屬性,用hasOwnProperty()檢查返回trueapp
console.log(p1.hasOwnProperty('name')) //true console.log(p1.hasOwnProperty('fun')) //true console.log(p1.hasOwnProperty('say')) //false console.log(p1.__proto__.hasOwnProperty('say')) true
二、this的指向:
類的方法內部若是有this,它默認是指向類的實例,但若是將該方法提出來單獨使用,this會指向該方法運行時的環境。所以咱們能夠使用bind綁定this,或者使用箭頭函數來解決。函數
class Logger{ printName(name){ this.print(`Hello ${name}`) } print(text){ console.log(text) } } const logger = new Logger(); const {printName} = logger; printName('Liane') //報錯
使用bind綁定thisthis
class Logger{ constructor(){ this.printName = this.printName.bind(this) } printName(name){ this.print(`Hello ${name}`) } print(text) { console.log(text) } } const logger = new Logger(); const {printName} = logger; printName('Liane') //'Hello Liane'
使用箭頭函數prototype
class Logger{ constructor(){ this.printName =(name)=>this.print(`Hello ${name}`); } print(text) { console.log(text) } } const logger = new Logger(); const {printName} = logger; printName('Liane') //'Hello Liane'
三、採用class表達式建立類
a、使用類的名字Me,只在class內部使用,指當前類,在外部則必須使用變量名MyClass引用code
const MyClass = class Me{ constructor(x,y){ this.x = x; this.y = y; } getClassName(){ return Me == this; } } let inst = new MyClass(1,2); console.log(inst.getClassName()) //Me console.log(inst.x) //1
若內部不使用Me,可以下簡寫對象
const MyClass = class{ /*...*/ }
採用class表達式可寫出當即執行的class繼承
let person = new class{ constructor(name){ this.name = name } sayName(){ console.log(this.name) } }('Liane'); person.sayName() //Liane
四、靜態方法:
類至關於實例的原型,全部在類中定義的方法,都會被實例繼承,若是在一個方法前,加上static關鍵字,就表示該方法不會被實例繼承(能夠被子類繼承),而是經過類來調用,這就稱爲靜態方法原型鏈
class Foo{ static fun(){ console.log("I'm a static function") } } Foo.fun() //"I'm a static function" var foo = new Foo() foo.fun() //TypeError:foo.fun is not a function
若static方法包含this,this指向類,而不是實例get
class Foo{ static bar(){ this.baz() } static baz(){ console.log('Hello') } baz(){ console.log('world') } } Foo.bar() //'Hello'
靜態方法能夠被子類繼承
class Parent{ static fun(){ return 'Im a static fun' } } class Child extends Parent{ foo(){ return super.fun() + ', too' } } Child.fun() //'Im a static fun' Child.foo() //'Im a static fun, too'
2、類的繼承
Class能夠經過extends關鍵字來實現繼承,這比ES5經過修改原型鏈實現繼承要清晰和方便得多。
語法:
class Person{ constructor(name,age){ this.name = name; this.age = age; } say(){ console.log(`My name is ${this.name}`) } } class Student extends Person{ constructor(x,y,score){ super(x,y); //super關鍵字,表示父類的構造函數,用來新建父類的this對象。 this.score = score; } } let st1 = new Student('Liane',18,99) console.log(st1){name: 'Liane', age: 18, score: 99}
子類必須在constructor方法中調用super方法,不然新建實例會報錯。由於子類本身的this對象必須先經過父類的構造函數完成塑造,獲得與父類一樣的實例屬性和方法。
判斷一個類是否繼承自另外一個類,能夠使用Object.getPrototypeOf()方法
Object.getPrototypeOf(Student)===Person //true Object.getPrototypeOf(st1)===Person //fales Object.getPrototypeOf(st1)===Student.prototype //true