在 JavaScript 中为 Google Closure 编译器注释 Singleton 对象,或“危险使用全局 this 对象”警告
我正在 ADVANCED_OPTIMIZATIONS 编译级别使用 Google Closure 编译器,并开始注释我的构造函数,因为我收到了各种警告:
警告 - 全局 this 对象的危险使用
对于我的“构造函数”类型函数,我将这样注释它们:
/**
* Foo is my constructor
* @constructor
*/
Foo = function() {
this.member = {};
}
/**
* does something
* @this {Foo}
*/
Foo.prototype.doSomething = function() {
...
}
这似乎工作正常,但是如果我有一个不是用 var myFoo = new 构造的“单例”对象怎么办Foo(); 我在文档中找不到如何注释这种类型的对象,因为它的类型只是对象,对吧?
Bar = {
member: null,
init: function() {
this.member = {};
}
};
I'm working with the Google Closure Compiler in ADVANCED_OPTIMIZATIONS compilation level and have started to annotate my constructors because I get all kinds of warnings:
WARNING - dangerous use of the global this object
For my 'constructor' type functions I'll annotate them like this:
/**
* Foo is my constructor
* @constructor
*/
Foo = function() {
this.member = {};
}
/**
* does something
* @this {Foo}
*/
Foo.prototype.doSomething = function() {
...
}
That seems to work fine, however what if I have a 'singleton' object that isn't constructed with var myFoo = new Foo();
I couldn't find in the documentation how to annotate this type of object because its type is just object right?
Bar = {
member: null,
init: function() {
this.member = {};
}
};
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
在 Closure 中创建单例的首选方式是这样的:
这允许单例的延迟实例化。像这样使用它:
请记住,这并不会阻止人们使用构造函数来创建
Bar
的实例。The preferred way of creating singletons in Closure is like this:
This allows for lazy instantiation of the singleton. Use it like this:
Keep in mind that this doesn't prevent people from using the constructor to create instances of
Bar
.这正是“危险使用此”警告您的潜在错误类型。在您的示例中,闭包编译器可能尝试将您的代码“扁平化”为:
注意:闭包编译器当前不会扁平化声明为全局对象的命名空间(即没有“ var”关键字在前面),所以您的代码现在可能仍然有效。但是,不知道在未来的版本中它不会这样做,并且您的代码会在没有警告的情况下突然中断。
当然,然后“Bar$member”和“Bar$init”将被重命名为“分别为“a”和“b”。这称为“命名空间扁平化”或“属性崩溃”。
您可以立即发现您的代码不再正常工作。在编译之前,如果你写:
this
将引用Bar
。然而,编译后它变成:this
将不再引用Bar
。相反,它指的是全局对象。这是编译器试图警告您以这种方式使用“this”是“危险”的方式,因为“this”可能会被更改为引用“全局”对象。这就是警告的真正含义。
简而言之,不要这样做。这种类型的编码风格会产生非常难以追踪的错误。
以这种方式修改代码:
或使用闭包:
在高级模式下使用闭包编译器时,不要尝试通过注释来消除警告。警告的出现是有原因的——它们试图警告你一些事情。
This is exactly the type of potential bug that "dangerous use of this" warns you against. In your example, the Closure Compiler may try to "flatten" your code to:
NOTE: The Closure Compiler currently will not flatten a namespace that is declared as a global object (i.e. without the "var" keyword in front), so your code may still work now. However, there is no telling that it won't do that in a future version and your code will suddenly break without warning.
Of course, then "Bar$member" and "Bar$init" will be renamed to "a" and "b" respectively. This is called "namespace flattening" or "collapsing of properties".
You can immediately see that your code no longer works correctly. Before compilation, if you write:
this
will refer toBar
. However, after compilation it becomes:this
will no longer refer toBar
. Instead it refers to the global object.This is way the compiler is trying to warn you that using "this" in such a way is "dangerous", because "this" may be changed to refer to the "global" object. That's the true meaning of the warning.
In short, DO NOT DO THIS. This type of coding style creates bugs that are very difficult to track down.
Modify your code this way:
or use a closure:
When using the Closure Compiler in Advanced Mode, do not try to get rid of warnings by annotating them away. Warnings are there for a reason -- they try to warn you about something.