参考
bilibili
视频itstrive
老师的课程(视频地址)。
ES5
中,需要用构造函数和原型链来模拟面向对象的实现。如下例:
function Person(name) {
this.name = name;
};
Person.prototype.showName = function () {
console.log("你好,我的名字叫" + this.name);
};
var don = new Person("don");
don.showName();
ES6
中,class
类作为对象的模板被引入,可以通过 class
关键字定义类,它的本质还是function
。可以看作一个语法糖,让对象原型的写法更加清晰、更像面向对象编程,将上例用class
来写的话如下:
class Person {
constructor(name) {
this.name = name;
}
showName() {
console.log("你好,我的名字叫" + this.name);
}
}
const don = new Person("don");
don.showName();
一、类的两种声明方式
要注意的是类的命名首字母大写,类的声明方式除了以上class
加上类名的声明式外,还有表达式声明:
class Person {
constructor(name) {
...
}
};
不过常用的话还是类的声明式。
二、类不存在变量提升
ES6
中的let
和const
都去除了变量提升机制,同样class
也是。
const don = new Person("don"); //Uncaught ReferenceError: Cannot access 'Person' before initialization
don.showName();
class Person {
constructor(name) {
this.name = name;
}
showName() {
console.log("你好,我的名字叫" + this.name);
}
};
三、类中的this
正常情况下访问class
中的this
都指向的是class
类的本身,也有特殊情况,如下:
class Person {
constructor(name) {
this.name = name;
}
showName() {
console.log("this指向的是" + this); //this指向的是undefined
console.log("你好,我的名字叫" + this.name);
}
};
const don = new Person("don");
const { showName } = don;
showName();
上例中,实例化完Person
后赋值给变量don
,再将don
解构出showName
,然后直接调用showName
函数,这里就会有问题了,因为js
中this
指向是谁调用就指向谁,本例中,showName
函数没有被任何对象调用,理应this
指向window
,不过因为ES6
默认遵循严格模式,所以输出undefined
。那应该如何解决这个this
指向问题呢?
class Person {
constructor(name) {
this.name = name;
this.showName = this.showName.bind(this);
}
showName() {
console.log("你好,我的名字叫" + this.name);
}
};
const don = new Person("don");
const { showName } = don;
showName();
只要在构造函数中将showName
函数的this
事先绑定好就可以了。
四、getter和setter
getter
是存值的时候调用的,setter
是设置值的时候调用的。
class Person {
constructor() {}
get name() {
return this._name;
}
set name(value) {
this._name = value;
}
};
const don = new Person();
don.name = "don";
console.log(don.name);
设置值的时候,比如don.name = "don"
会触发setter
,当console.log(don.name);
获取的时候会触发getter
。
五、类的静态方法
class
本身方法,即直接定义在类内部的方法,不需要实例化。 ES6
中规定,Class
内部只有静态方法,没有静态属性。声明一个类的静态方法需要用static
关键字。
class Person {
constructor(name) {
this.name = name;
}
showName() {
console.log("你好,我的名字叫" + this.name);
}
static showAge() {
console.log("你好,我的年龄是18");
}
}
Person.showAge();
六、类的继承
function Person(name) {
this.name = name;
}
Person.prototype.showName = function () {
console.log("你好,我的名字叫" + this.name);
};
function Student(name, age) {
Person.call(this, name);
this.age = age;
};
Student.prototype = new Person();
var don = new Student("don", 28);
don.showName();
以上是ES5
的继承,即原型链继承,Student
继承自Person
,继承实现需要2个步骤:
- 在
Student
构造函数中调用Person
函数并通过手动修改this
将Person
的属性添加到Student
。 - 将
Person
实例化对象赋值给Student
的prototype
。
接下来看下ES6
又是怎么实现的:
class Person {
constructor(name) {
this.name = name;
}
showName() {
console.log("你好,我的名字叫" + this.name);
}
}
class Student extends Person {
constructor(name, age) {
super(name);
this.age = age;
}
}
var don = new Student("don", 28);
ES6
中需要通过extends
关键字来实现继承父级,在子类constructor
执行super
函数表示执行父类的constructor
。
在继承中,父类有个showName
函数,如果子类也想有个showName
函数并且希望父类的showName
也可以执行,该怎么处理?
class Person {
constructor(name) {
this.name = name;
}
showName() {
console.log("你好,父类的名字叫" + this.name);
}
}
class Student extends Person {
constructor(name, age) {
super(name);
this.age = age;
}
showName() {
super.showName();
console.log("你好,子类的名字叫" + this.name);
}
}
var don = new Student("don", 28);
don.showName();
主要借助super
来实现,super
也可以在子类的函数中调用,表示父类本身。
网友评论