var A = class{test(){}} 和 class A{test()}有什么区别啊
发布于 6 年前 作者 rosencai 2454 次浏览 来自 问答

var A = class{ test(){} } class A{ test(){} } 这两种写法有什么区别,用起来有什么区别,面试被问道了,不会,很尴尬

6 回复

没区别啊。。。。。。。。。

前者有变量提升,后者没有

@lizhenwu 初始化没有变量提升的

来自酷炫的 CNodeMD

前者是匿名类,后者有名字。

@lizhenwu 变量提升是 ES5里面的 函数才有 ES6的 class 不会提升

前者是类表达式(ClassExpression)+赋值表达式(AssignmentExpression ),后者是类声明(ClassDeclaration)

类表达式:

ClassExpression[Yield, Await]:
    classBindingIdentifier[?Yield, ?Await] opt ClassTail [?Yield, ?Await]

类声明:

ClassDeclaration[Yield, Await, Default]:
    classBindingIdentifier[?Yield, ?Await] ClassTail [?Yield, ?Await] 
    [+Default] classClassTail [?Yield, ?Await]

从规范中可以看出,前者的类名(classBindingIdentifier)可以省略,而后者不行。

class {}      // 类声明: SyntaxError: Unexpected token {
var A = class {}  // 类表达式: √

对于类声明,只有一种情况可以省略类名,就是在 export 语句中:

ClassDeclaration:class ClassTail only occurs as part of an ExportDeclaration and the setting of a name property and establishing its binding are handled as part of the evaluation action for that production.

export default class {};		// √ 类声明

关于变量提升,其实类声明和函数声明不同,类声明存在变量提示。

new A();
class A{};
// ReferenceError: A is not defined

fn();
function fn(){};
// √

只所以 class 和 function 的提示规则不同,是因为 class 还涉及到了继承。考虑如下代码,如果存在类声明的变量提升,那么:

let A = class{};  // 不提示
class B extends A{}  // 提示

第一行代码是类表达式,不提示。第二行是类声明,如果把第二行提升了,那么就会报错,因为 A 还未定义。

回到顶部