ES6 Class类,就是构造函数语法糖?
一、Class 类可以看作是构造函数的语法糖
ES6引入了 Class(类)这个概念,作为对象的模板。通过
class
关键字,可以定义类。constructor()
方法,这就是构造方法,而this
关键字则代表实例对象
。类的所有方法都定义在类的prototype
属性上面,方法前面不需要加上function
这个关键字,直接把函数定义放进去了就可以了。使用的时候,类必须使用new
调用跟构造函数的用法完全一致。
- 类不存在变量提升
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
toString() {
return '(' + this.x + ', ' + this.y + ')';
}
}
var p = new Point(1, 2);
通过代码证明:
class Point {
// ...
}
typeof Point // "function"
Point === Point.prototype.constructor // true
类的数据类型就是函数,类本身就指向构造函数。
constructor: 方法是类的默认方法,通过
new
命令生成对象实例时,自动调用该方法。一个类必须有constructor()
方法,如果没有显式定义,一个空的constructor()
方法会被默认添加。
class Point {
}
// 等同于
class Point {
constructor() {}
}
取值函数(getter)和存值函数(setter)
class Person {
constructor(name, age) {
this.name = name
this.age = age
}
get nl() {
return this.age
}
set nl(value) {
this.age = value
}
}
let p = new Person('fzw', 25)
console.log(p.nl);
p.nl = 44
console.log(p.nl);
class表达式
let person = new class {
constructor(name) {
this.name = name;
}
sayName() {
console.log(this.name);
}
}('张三');
person.sayName(); // "张三"
上面代码中,person
是一个立即执行的类的实例。
二、静态方法、静态属性
类相当于实例的原型,所有在类中定义的方法,都会被实例继承。如果在一个方法前,加上
static
关键字,就表示该方法不会被实例继承,而是直接通过类来调用,这就称为“静态方法”。
class Foo {
static classMethod() {
this.baz(); // 'hello'
return '我被调用了';
}
static baz() {
console.log('hello');
}
baz() {
console.log('world');
}
}
console.log(Foo.classMethod()); // 我被调用了
var foo = new Foo();
foo.classMethod() // TypeError: foo.classMethod is not a function
注意 如果静态方法包含this
关键字,这个this
指的是类,而不是实例。静态方法可以与非静态方法重名。
class Foo {
static classMethod() {
return 'hello';
}
}
class Bar extends Foo {
}
Bar.classMethod() // 'hello'
父类的静态方法,可以被子类继承。父类Foo
有一个静态方法,子类Bar
可以调用这个方法。
静态方法也是可以从super
对象上调用的。
class Foo {
static classMethod() {
return 'hello';
}
}
class Bar extends Foo {
static classMethod() {
// super在静态方法之中指向父类
return super.classMethod() + ', too';
}
}
console.log(Bar.classMethod());
注意 super
在静态方法之中指向父类。
静态属性
static
关键词修饰,可继承使用
class MyClass {
static myStaticProp = 42;
constructor() {
console.log(MyClass.myStaticProp); // 42
}
}
class Bar extends MyClass {
}
new MyClass()
console.log(Bar.myStaticProp);
三、私有方法和私有属性
用
#
修饰属性或方法,私有属性和方法只能在类的内部使用。
私有属性也可以设置 getter 和 setter 方法
私有属性和私有方法前面,也可以加上static
关键字,表示这是一个静态的私有属性或私有方法。
class Counter {
#xValue = 0;
constructor() {
console.log(this.#x);
}
get #x() { return this.#xValue; }
set #x(value) {
this.#xValue = value;
}
}
四、class 继承
- Class 可以通过
extends
关键字实现继承,让子类继承父类的属性和方法。- ES6 规定,子类必须在
constructor()
方法中调用super()
,如果不调用super()
方法,子类就得不到自己的this
对象。调用super()
方法会执行一次父类构造函数。- 在子类的构造函数中,只有调用
super()
之后,才可以使用this
关键字,
class Foo {
constructor() {
console.log(1);
}
}
class Bar extends Foo {
constructor(color) {
// this.color = color; // ReferenceError
super();
this.color = color; // 正确
}
}
const bar = new Bar('blue');
console.log(bar); // Bar {color: 'blue'}
super 关键字
super
这个关键字,既可以当作函数使用,也可以当作对象使用。
super
作为函数调用时,代表父类的构造函数。只能用在子类的构造函数之中,用在其他地方就会报错。super
作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类。
作为对象,普通方法中super指向父类的原型对象
class A {
constructor() {
this.x = 1;
}
print() {
console.log(this.x);
}
}
class B extends A {
constructor() {
super();
this.x = 2;
}
m() {
super.print();
}
}
let b = new B();
b.m() // 2
注意:
在子类普通方法中通过super
调用父类的方法时,方法内部的this
指向当前的子类实例。
作为对象,静态方法之中,这时super
将指向父类
class Parent {
static myMethod(msg) {
console.log('static', msg);
}
myMethod(msg) {
console.log('instance', msg);
}
}
class Child extends Parent {
static myMethod(msg) {
// super 代表父类
super.myMethod(msg);
}
myMethod(msg) {
// super 代表父类原型对象
super.myMethod(msg);
}
}
Child.myMethod(1); // static 1
var child = new Child();
child.myMethod(2); // instance 2
extends 关键字
// 1、构造器原型链
Child.__proto__ === Parent; // true
Parent.__proto__ === Function.prototype; // true
Function.prototype.__proto__ === Object.prototype; // true
Object.prototype.__proto__ === null; // true
// 2、实例原型链
child.__proto__ === Child.prototype; // true
Child.prototype.__proto__ === Parent.prototype; // true
Parent.prototype.__proto__ === Object.prototype; // true
Object.prototype.__proto__ === null; // true
extends
继承,主要就是:
- 把子类构造函数(
Child
)的原型(__proto__
)指向了父类构造函数(Parent
),- 把子类实例
child
的原型对象(Child.prototype
) 的原型(__proto__
)指向了父类parent
的原型对象(Parent.prototype
)。这两点也就是图中用不同颜色标记的两条线。
子类构造函数
Child
继承了父类构造函数Parent
的里的属性,使用super
调用的。
来源:juejin.cn/post/7225511164125855781