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