一、基本语法
通过class关键字,可以定义类。该方法定义的原型对象跟ES5定义的没有多少区别,只是用class的写法能让对象原型的定义更加清晰,更像面向对象编程的语法。
1、基本语法:
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()检查返回true
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
2、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绑定this
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'
使用箭头函数
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'
3、采用class表达式创建类
a、使用类的名字Me,只在class内部使用,指当前类,在外部则必须使用变量名MyClass引用
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
4、静态方法:
类相当于实例的原型,所有在类中定义的方法,都会被实例继承,如果在一个方法前,加上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指向类,而不是实例
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'
二、类的继承
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
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。