为何被称为语法糖?
- 它的class和别的语言不一样,它依旧是基于原型继承的实现,对语言的功能并没有影响,只是方便了你的书写及阅读.
声明了一个类
类的名字叫做Person (注意:类名首字母最好大写)
constructor就是指构造函数,而后面的方法就是对象原型上的方法,如果在方法前加了static,就会变成静态方法,即只有类自己本身可以访问,实例不能访问。
class Person {
constructor(name) {
this.name = name;
} //注意:class里面每个{}后面是不用加','的,加了会报错
sayName() {
console.log(this.name);
}
static sayHello() { //静态方法:只有自己能访问,实例无法访问
console.log('hello');
}
}
let person = new Person('zjf');
person.sayName(); //'zjf'
相当于:
function Person(name) {
this.name = name;
}
Person.prototype.sayName = function() {
console.log(this.name);
};
Person.sayHello = function() {
console.log('hello');
};
类也有两种存在形式:声明和表达式 :两者都不会被提升,不会像函数声明一样被提升
声明:
class Person {
...
}
表达式:
let Person = class {
...
}
那么类的类型是什么?
- 类的类型依旧是函数,所以类声明其实就是创建了一个具有构造函数方法行为的函数
console.log(typeof Person); //"function"
- 既然本质是函数,那么类也能被作为一等公民(函数是JS的一等公民),可以被作为参数,也可以传入函数,可以赋值给变量等等
function createClass(Person) {
return new Person();
}
let Person = class {
sayHello() {
console.log('hello');
}
};
let person = createClass(Person);
person.sayHello();
实现继承:
- class语法糖大大简化了继承,使用extends关键字实现继承,不用担心construcor指向,可以使用super直接调用基类的构造函数
class Person {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}
class person extends Person { //使用extends关键字实现继承
constructor(name, age) {
super(name); //super调用基类的构造函数,一定要写在最前面,只能在派生类中使用
this.age = age;
}
sayAge() {
console.log(this.age);
}
}
let man = new person('zjf',22);
man.sayName(); //'zjf'
man.sayAge(); //'22'
- 关于super()调用的注意点
- 派生类(继承自其他类的类)中指定了构造函数就必须调用super(),没有的话会报错,且super()只能存在于派生类
- super()一定要写在构造函数的最前面,因为它负责初始化this,如果写后面this指向会出现问题
- 如果不想用super(),可以让构造函数返回一个对象
- super也可以使实例使用被派生类覆盖掉的同名基类的方法
class person extends Person {
constructor(name) {
super(name);
}
sayName() {
return super.sayName() //调用了Person.prototype.sayName()
}
}