元属性
在第三章的“new.target
”一节中,我们引入了一个ES6的新概念:元属性。正如这个名称所暗示的,元属性意在以一种属性访问的形式提供特殊的元信息,而这在以前是不可能的。
在new.target
的情况下,关键字new
作为一个属性访问的上下文环境。显然new
本身不是一个对象,这使得这种能力很特殊。然而,当new.target
被用于一个构造器调用(一个使用new
调用的函数/方法)内部时,new
变成了一个虚拟上下文环境,如此new.target
就可以指代这个new
调用的目标构造器。
这是一个元编程操作的典型例子,因为它的意图是从一个构造器调用内部判定原来的new
的目标是什么,这一般是为了自省(检查类型/结构)或者静态属性访问。
举例来说,你可能想根据一个构造器是被直接调用,还是通过一个子类进行调用,来使它有不同的行为:
class Parent {
constructor() {
if (new.target === Parent) {
console.log( "Parent instantiated" );
}
else {
console.log( "A child instantiated" );
}
}
}
class Child extends Parent {}
var a = new Parent();
// Parent instantiated
var b = new Child();
// A child instantiated
这里有一个微妙的地方,在Parent
类定义内部的constructor()
实际上被给予了这个类的词法名称(Parent
),即便语法暗示着这个类是一个与构造器分离的不同实体。
警告: 与所有的元编程技术一样,要小心不要创建太过聪明的代码,而使未来的你或其他维护你代码的人很难理解。小心使用这些技巧。