注册
web

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 关键字


168fb9a3828f9cb4_tplv-t2oaga2asx-zoom-in-crop-mark_4536_0_0_0.awebp
    // 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 继承,主要就是:



  1. 把子类构造函数(Child)的原型(__proto__)指向了父类构造函数(Parent),
  2. 把子类实例child的原型对象(Child.prototype) 的原型(__proto__)指向了父类parent的原型对象(Parent.prototype)。

这两点也就是图中用不同颜色标记的两条线。



子类构造函数Child继承了父类构造函数Parent的里的属性,使用super调用的。




作者:f_人生如戏
来源:juejin.cn/post/7225511164125855781

0 个评论

要回复文章请先登录注册