Function实现一个Class
function person(name, age) {
this.name = name
this.age = age
}
person.prototype.getName = function() {
console.log('person name is:'+ this.name)
}
const person = new person('xiaoye', 18)
person.getName() // person name is:xiaoye
person.age // 18
// 等价于
class Person {
// Person构造函数
constructor(name, age) {
this.name = name
this.age = age
}
// Person原型上的方法
getName() {
console.log('person name is:'+ this.name)
}
}
const person = new Person('xiaoye', 18)
person.getName() // person name is:xiaoye
person.age // 18
通过上述结果,可以得出class就是一个关键字,是function的一个
语法糖。class中的constructor就是其构造函数,里面的方法就是挂载在原型上的方法,在class中定义的方法不需要通过function去定义,否则会报错。
Class的静态属性
class Person {
static height=180
// Person构造函数
constructor(name, age) {
this.name = name
this.age = age
}
// Person构造函数的方法
static setAge(age) {
this.age = age
}
static getAge() {
console.log('person age is:'+ this.age)
}
getInfo() {
this.getAge()
}
getStaticAge() {
Person.getAge()
}
getHeight(){
console.log('person height is:' + Person.height)
}
}
const person = new Person('xiaoye', 18)
person.getAge() // Uncaught TypeError: person.getAge is not a function
person.getInfo() // Uncaught TypeError: this.getAge is not a function
person.getStaticAge() // person age is:undefined
Person.getAge() // person age is:undefined
Person.setAge(12)
person.getStaticAge() // person age is:12
Person.getAge() // person age is:12
由于静态方法是挂载在构造函数的对象上在原型上是找不到的,所以只能被通过Person直接对其进行调用。
Class的私有属性
class Person {
// Person构造函数
constructor(name, age) {
this.name = name
this.age = age
}
getAge() {
console.log(this.age)
}
#getName() {
console.log(this.name)
}
getInfo() {
this.getAge()
this.#getName()
}
}
const person = new Person('xiaoye', 18)
this.getAge() // 18
this.getName() // VM706:1 Uncaught TypeError: person.getName is not a function
this.getInfo() // 18 xiaoye
通过
#可以将类中的方法和属性设置为私有属性,只能在类中被进行调用
extends继承
class Parent {
constructor() {
this.parentName = 'xiaoye';
this.parentAge = 20;
}
parentFunc() {
console.log(this.parentName);
}
}
// class Child extends Parent 等价于 Child.prototype = new Parent()
class Child extends Parent {
constructor() {
super(); // 等价于 Parent.call(Child.prototype)
this.childName = 'xiaoming';
this.childAge = 18;
}
childFunc() {
console.log(this.childName)
}
}
let child = new Child();
class的继承的设计思想在我看来就是利用了组合继承的优点来实现的,可以达到:
1.继承父类原型方法
2.可以向父类传递参数
3.子类继承父类的引用类型属性不会被共享的优点。
super关键字
class Parent {
constructor() {
this.parentName = 'xiaoye';
this.parentAge = 20;
}
parentFunc() {
console.log(this.parentName);
}
}
// class Child extends Parent 等价于 Child.prototype = new Parent()
class Child extends Parent {
constructor() {
this.childName = 'xiaoming';
this.childAge = 18;
}
childFunc() {
console.log(this.childName)
}
}
let child = new Child(); // Uncaught ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor
子类必须在
constructor方法中调用super方法,否则新建实例时会报错。这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super方法,子类就得不到this对象。所以在上述继承中导致新建实例时报错。
super的两种场景
构造函数
class Parent {
constructor() {
}
}
class Child extends Parent {
constructor() {
super();
this.age = 18
}
childFunc() {
super(); //Uncaught SyntaxError: 'super' keyword unexpected here
}
getAge() {
console.log(this.age)
}
}
let child = new Child();
super在constructor中会被当做构造函数来看待,等价于
A.prototype.constructor.call(this),并且在super()不能在其他方法中进行使用,否则会报错
引用对象
class Parent {
constructor(name) {
this.name = name
}
getName() {
console.log(this.name)
}
}
class Child extends Parent {
constructor(name) {
super(name);
this.age = 18
}
getParentName() {
super.getName();
}
}
let child = new Child('xiaoye');
child.getParentName() // xiaoye
super在方法中会被当做引用类型来看待,不能在consructor中使用,否则会报错
总而言之,class的出现就是为了使程序可以更加面向对象开发,相比es5的继承写法更加直观,实际的底层实现还是围绕着原型链进行开展的,如果读不懂可以阅读一下本人前面几篇关于原型链的文章巩固下原型链相关的基础再进行阅读。