【问题标题】:Why class name can be referenced inside class even after it was redefined?为什么类名被重新定义后仍可以在类内部引用?
【发布时间】:2019-02-18 09:24:28
【问题描述】:

您所期望的以下内容不起作用:

let User = {
    foo() {
        User.prop = 1;
    }
};

let User2 = User;
User = null;

User2.foo();  // Cannot set property of null
console.log(User2.prop);

不过,这行得通:

class User {
    static foo() {
        User.prop = 1;
    }
}

let User2 = User;
User = null;

User2.foo();
console.log(User2.prop);  // 1

既然函数和类都是对象,而且在这两种情况下我都为它设置了一个属性,为什么结果会不同呢?它在哪里获得User 参考?

【问题讨论】:

  • 请注意,您的第一个示例没有在任何东西上使用静态方法,它更像是 constructor 类中的代码。我可以编辑澄清一下吗?
  • 我不确定你的意思。我的原始代码有一个函数,一旦被调用,它就会为自己设置一个属性(因为它是一个对象)。为什么你认为有必要引入 User 对象?
  • 这样调用(User2.foo();)的方式在两个例子中都是一样的,区别更明显。如果你想使用一个函数,也可以写let User = function() {}; User.foo = function() { User.prop = 1; };。随意编辑或回滚我的更改 - 这是你的问题!

标签: javascript ecmascript-6 scope es6-class


【解决方案1】:

类似于named function expressionsclasses 被包装在一个额外的范围内,其中包含一个不可变的绑定及其名称和值。

如果我们忠实地将 class 语法脱糖到 ES5,我们会得到类似的东西

let User = (() => {
    const User = function() {};
//  ^^^^^^^^^^
    User.foo = function() {
        User.prop = 1;
    };
    return User;
})();

let User2 = User;
User = null;

User2.foo();
console.log(User2.prop);  // 1

这个内部的User 声明是foo 方法正在关闭的声明。覆盖外部变量无关紧要。

【讨论】:

【解决方案2】:

在类的声明中,该类的名称是永久绑定的。这只是老式构造函数类和正确的 ES2015 类之间的区别之一。 (另一个重要的区别是给定名称的函数可以安全地重新声明,但同名的类不能。)

【讨论】:

    【解决方案3】:

    在第二个示例中,您得到 1,因为它引用了一个静态变量,即使它在使用前未实例化的类中。删除静态并正确实例化它仍然返回 1:

    class User {
        foo() {
            this.prop = 1;
        }
    }
    
    let User2 = new User();
    User = null;
    
    User2.foo();
    console.log(">>" + User2.prop);  // 1
    

    注意User = null 无关紧要。

    【讨论】:

    • 这不是 OP 所要求的
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-16
    • 1970-01-01
    • 1970-01-01
    • 2013-04-12
    • 2010-12-21
    相关资源
    最近更新 更多