为什么 class 名称在 class 中被重新定义后仍然可以被引用?
Why class name can be referenced inside class even after it was redefined?
如您所料,以下内容不起作用:
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
参考?
在第二个例子中,你得到 1 是因为引用了一个静态变量,即使它在 class 中,在使用它之前没有实例化。删除静态并正确实例化它 return 1 无论如何:
class User {
foo() {
this.prop = 1;
}
}
let User2 = new User();
User = null;
User2.foo();
console.log(">>" + User2.prop); // 1
注意 User = null
无关紧要。
与 named function expressions 类似,class
es 被包裹在一个额外的作用域中,该作用域包含一个不可变的绑定及其名称和值。
如果我们忠实地将 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
方法正在关闭的声明。覆盖外部变量对它来说无关紧要。
在 class 的声明中,class 的名称是永久绑定的。这只是老式构造函数 classes 和正确的 ES2015 classes 之间的区别之一。 (另一个重要的区别是可以安全地重新声明给定名称的函数,但是 class 同名函数不能。)
如您所料,以下内容不起作用:
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
参考?
在第二个例子中,你得到 1 是因为引用了一个静态变量,即使它在 class 中,在使用它之前没有实例化。删除静态并正确实例化它 return 1 无论如何:
class User {
foo() {
this.prop = 1;
}
}
let User2 = new User();
User = null;
User2.foo();
console.log(">>" + User2.prop); // 1
注意 User = null
无关紧要。
与 named function expressions 类似,class
es 被包裹在一个额外的作用域中,该作用域包含一个不可变的绑定及其名称和值。
如果我们忠实地将 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
方法正在关闭的声明。覆盖外部变量对它来说无关紧要。
在 class 的声明中,class 的名称是永久绑定的。这只是老式构造函数 classes 和正确的 ES2015 classes 之间的区别之一。 (另一个重要的区别是可以安全地重新声明给定名称的函数,但是 class 同名函数不能。)