JavaScript中new super.SomeProperty形式的表达式是否合法?
new super.SomeProperty a valid JavaScript expression? 这个问题真的挺有意思——你观察到的跨浏览器差异,其实反映了早期ECMAScript规范落地时,不同浏览器引擎对语法细节的不同解读。咱们一步步拆解清楚:
首先明确结论:根据ECMAScript 2015及后续的官方规范,new super.SomeProperty本身是合法的语法,但你遇到的报错情况,是早期浏览器引擎实现规范时的分歧导致的,现代主流浏览器已经逐步统一了行为。
先看你给出的测试代码:
class Test { test() { return new super.constructor; } } console.log((new Test).test());
这段代码的逻辑是:在Test类的test方法里,super.constructor指向的是Test的父类构造函数(因为Test没有显式继承其他类,默认父类是Object)。理论上,new super.constructor等价于new Object(),应该返回一个空对象——这也是Firefox和Edge的行为。
那为什么Chrome和Safari会报错?
- Safari的
SyntaxError:早期Safari的JavaScriptCore引擎,可能把super当成了普通标识符,没有正确识别super.PropertyName作为new操作符后的合法表达式,所以直接抛出语法错误。不过现在新版本的Safari已经修复了这个问题。 - Chrome的
ReferenceError:早期V8引擎在处理super作为new操作目标时,错误地认为super没有绑定到当前方法的原型上下文,导致无法正确解析super.constructor。同样,新版本的Chrome也已经修正了这个行为。
再结合ECMAScript规范来看:
规范里明确,new操作符后面可以跟任何能求值为构造函数的表达式,而super.PropertyName是合法的“SuperProperty”表达式——它会沿着当前类的原型链查找指定属性。所以从语法和执行逻辑上,new super.SomeProperty完全符合规范,只要super.SomeProperty是一个可被new调用的构造函数,就应该正常执行。
你提到的规避方法(给super.constructor加括号new (super.constructor),或者先赋值给变量再使用)之所以有效,是因为它们消除了引擎对表达式优先级的解析歧义:
- 加括号强制引擎先求值
super.constructor,再把结果传给new操作符; - 赋值给变量则提前把
super.constructor的结果存储下来,避免了引擎对复杂表达式的误判。
最后再总结一下:
- 语法合法性:
new super.SomeProperty是完全合法的ECMAScript表达式; - 跨浏览器差异:是早期引擎实现规范时的历史问题,现代主流浏览器(更新到最新版)都会返回空对象,和Firefox/Edge的行为一致;
- 稳妥写法:如果需要兼容旧版本浏览器,使用括号或变量的规避方案是非常靠谱的选择。
内容的提问来源于stack exchange,提问作者GOTO 0

