1

今天是系列第五篇,主要讲一下上一篇遗留下来的es6继承的具体使用问题。因为在es6继承中用到了一些语法糖,书写方式跟es5的继承写法上有很大的不同,所以专门把它拎出来讲。言归正传,下面我将其对应的一些关键字的用法进行阐述,并配合一些例子来解释。

constructor

  • 定义:是类的构造函数。
  • 用法:在使用 new 实例化对象的时候,会自动调用这个方法。
  • 注意:一个类必须有 constructor 方法,如果没有显式定义,会默认添加 consructor 方法。所以即使你没有添加构造函数,也是会有一个默认的构造函数的。一般 constructor 方法返回当前实例对象 this ,但是也可以指定 constructor 方法返回一个全新的对象,让返回的实例对象不是该类的实例。

举个例子:

class Demo{
    say(){
        console.log('我在创建一个例子')
    }
}
const demo = new Demo()
console.log(demo)  // demo {__proto__:{constructor:###, say:function(){###}}}
demo.say()  // 我在创建一个例子

在上面这个例子中创建了一个Demo类,并且没有创建constructor方法。打印实例化对象demo,我们可以看到在该对象的__proto__方法下有constructor属性和say方法,所以可以证明上面的结论:在没有显式定义constructor方法的时候,会默认添加一个返回this(指向实例)的构造函数。

super

  • 定义:它是一个用于访问父类对象上函数的关键字。
  • 用法:可以当做函数使用,也可以当做对象使用。即存在super(…)或者super.xxx(…)这两种使用方式。单独调用super会报错

    • 作为函数使用时(看例子):

      • 如果想让实例对象使用到构造函数中的属性,在 constructor 中必须调用 super 方法,因为子类没有自己的this对象,而是继承父类的this对象,而super就代表了父类的构造函数。super虽然代表了父类的构造函数,但是返回的是子类的实例,即super内部的this指的是子类。
      • 如果只是想调用该类的原型方法时,在 constructor中就可以不用调super方法。只需要再constructor方法中手动返回一个值即可
// 没有调用super的情况
class Demo{
    construcor(){
        return 1
    }
    say(){
        console.log('我创建了一个demo')
    }
}
const demo = new Demo()
demo.say() // 我创建了一个demo
- 当做对象使用:
    - 在普通方法中,指向父类的原型对象;所以在子类的方法中super.print();指向的是父类原型上的方法。
    - 在静态方法中,指向父类。但是因为super的两种用法,所以es6规定在使用必须要明确使用方式,像单独console.log(super) 就会报错。
    ```
    // demo1,普通方法
    class A {
        constructor() {
            this.x = 1
        }
        say(){
            console.log('说话')
        }
    }

    class B extends A {
        constructor() {
            super();
            super.x = 3;
            // super指向父类的原型对象,原型对象里没有父类实构造函数的属性
            console.log(super.x); // undefined
            // say是在原型链上父类的原型方法,可以获取到
            console.log(super.say === this.say); // true
            console.log(this.x); // 3
        }
    }

    let b = new B();




    // demo2,静态方法指向父类
    class A {
        static say() {
            console.log('说话')
        }
    }

    class B extends A {
        constructor() {
            super();
        }
        static action(){
            super.say()
        }
    }

    B.action()  // 说话
    ```

  • 注意:super的使用方式只有super()和super.###()这两种。这一点比较特殊,如果直接单独使用super,如console.log(super)时,就会抛出错误。

static

  • 创建静态方法的关键字。类相当于实例的原型, 所有在类中定义的方法, 都会被实例继承。 如果在一个方法前, 加上static关键字, 就表示该方法不会被实例继承, 而是直接通过类来调用。静态方法调用直接
    在类上进行,而在类的实例上不可被调用。静态方法通常用于创建 实用/工具 函数。

new.target

  • 定义:检测函数或构造方法是否是通过new运算符被调用的。
  • new.target使用的场景

    • 通过new运算符被初始化的函数或构造方法中,new.target返回一个指向构造方法或函数的引用。
    • 在普通的函数调用中,new.target的值是undefined。

看栗子:

class A {
    constructor(name, age){
        this.name = name
        this.age = age
        console.log(new.target === A) // true
    }
    say() {
        // new.target === undefined
        console.log(`我叫${this.name},今年${this.age}岁,看看new.target的值:${new.target}`)
    }
}
const a = new A('小李', 20)
a.say()

总结

  • constructor

    • 是类的构造函数。
    • 在使用 new 实例化对象的时候,会自动调用这个方法。
  • super

    • 是一个用于访问父类对象上函数的关键字。
    • 可以当做函数使用,也可以当做对象使用。即存在super(…)或者super.xxx(…)这两种使用方式,单独调用super会报错。但是两种使用super方法的指向是不同的,这点需要特别注意一下。

      • 在子类constructor调用super()时,其内部this指向子类
      • 作为对象使用:

        • 在普通方法中,指向父类的原型对象
        • 在静态方法中,指向父类
  • static

    • 创建静态方法的关键字
  • new.target

    • 检测函数或构造方法是否是通过new运算符被调用的。
    • 在构造函数中调用,指向构造方法或者函数的应用;作为普通函数返回undefiend

参考资料


摩根
11 声望2 粉丝

前端工程师