元属性new.target

在es5中,通常判断一个对象是否是一个类的实例的时候使用instanceof关键字,例如如下代码

function Person(name) {
    if (this instanceof Person) {
        this.name = name
    } else {
        throw new Error('必须使用new关键字来调用Person')
    }
}

当判断this不是Person类的实例的时候,将会抛出一个异常。

但是如下通过callapply修改this绑定作用域,那么在Person类中是无法区分到底是通过Person.call()Person.apply()还是new关键字调用得到的Person实例。

所以,如下代码也能够正常执行:

let person = new Person('Leevare')
let anotherPerson = Person.call(person, 'Jason')

在es6中引入了new.target这个元属性。当通过new的方式调用时,new.target将会被赋予新创建的对象实例,此处则为Person,其它方式将会为undefined。所以可以将上述的代码修改为如下:

function Person(name) {
    if(new.target !== Person) {
        throw new Error('必须使用new关键字来调用Person')
    }else {
        this.name = name
    }
}

此时,若使用callapply则会抛出异常。

利用new.target的这一特性,可以实现一个只能被继承,而不能被实例化的类。

class Parent {
    constructor() {
        if (new.target === Parent) {
            throw new Error('Parent不能被实例化')
        }
    }
}

class Child extends Parent {
    constructor(a, b) {
        super()
    }
}

const child = new Child(1, 2)
const parent = new Parent() //报错
如果您觉得本文对您有用,欢迎捐赠或留言~
微信支付
支付宝

发表评论

您的邮箱地址不会被公开。 必填项已用 * 标注