google 闭包编译器的高级优化并未优化某些变量

发布于 2024-11-18 22:27:04 字数 1093 浏览 1 评论 0原文

我遇到了带有高级优化的 Google Closure Javascript 编译器的问题。正如文档所建议的,为了保留导出的Javascript,我做了这样的事情:

var myClass = function() {
   this["myFunc"] = this.myFunc;
   this["myFunc2"] = this.myFunc2;
};
window["myClass"] = myClass;

myClass.prototype = {
    myFunc: function() { alert("myFunc"); },
    myFunc2: function() { alert("myFunc2"); }
};

问题是,有时,无论出于何种原因,myFuncmyFunc2不会被缩短,而且我在最终输出中看到这样的代码:

x.myFunc=x.myFunc;x.myFunc2=x.myFunc2;

这显然不太理想。

我怎样才能防止这种情况发生?


进一步的实验表明,某些关键字(例如“get”)不会被编译。

var myClass = function() {
   this["get"] = this.get;
   this["myFunc2"] = this.myFunc2;
};
window["myClass"] = myClass;

myClass.prototype = {
    get: function() { alert("myFunc"); },
    myFunc2: function() { alert("myFunc2"); }
};

编译成

function a() {
  this.get = this.get;
  this.myFunc2 = this.a
}
window.myClass = a;
a.prototype = {get:function() {
  alert("myFunc")
}, a:function() {
  alert("myFunc2")
}};

我仍然不知道是什么原因造成的。

I'm running into an issue with the Google Closure Javascript compiler with advanced optimization. As the documentation suggests, to preserve exported Javascript I do something like this:

var myClass = function() {
   this["myFunc"] = this.myFunc;
   this["myFunc2"] = this.myFunc2;
};
window["myClass"] = myClass;

myClass.prototype = {
    myFunc: function() { alert("myFunc"); },
    myFunc2: function() { alert("myFunc2"); }
};

The issue is that sometimes, for whatever reason, myFunc and myFunc2 don't get shortened, and I see code like this in the final output:

x.myFunc=x.myFunc;x.myFunc2=x.myFunc2;

This is obviously less than ideal.

How can I prevent this from happening?


Further experimentation has shown that there are certain keywords, e.g. 'get' that don't get compiled.

var myClass = function() {
   this["get"] = this.get;
   this["myFunc2"] = this.myFunc2;
};
window["myClass"] = myClass;

myClass.prototype = {
    get: function() { alert("myFunc"); },
    myFunc2: function() { alert("myFunc2"); }
};

Compiles into

function a() {
  this.get = this.get;
  this.myFunc2 = this.a
}
window.myClass = a;
a.prototype = {get:function() {
  alert("myFunc")
}, a:function() {
  alert("myFunc2")
}};

I still don't know what's causing it though.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

痴情换悲伤 2024-11-25 22:27:04

我无法重复你的问题。如果我转到 http://closure-compiler.appspot.com/home 并编译以下内容:

// ==ClosureCompiler==
// @compilation_level ADVANCED_OPTIMIZATIONS
// @output_file_name default.js
// ==/ClosureCompiler==

var myClass = function() {
  this["myFunc"] = this.myFunc;
  this["myFunc2"] = this.myFunc2;
};
window["myClass"] = myClass;

myClass.prototype = {
  myFunc: function() { alert("myFunc"); },
  myFunc2: function() { alert("myFunc2"); }
};

然后我得到以下结果:

function a(){this.myFunc=this.a;this.myFunc2=this.b}window.myClass=a;a.prototype={a:function(){alert("myFunc")},b:function(){alert("myFunc2")}};

属性被重命名,如预期的那样。

至于你的第二个例子,它与称为

如果您查看 CommandLineRunner.java,您将看到 externs 文件夹。这些文件的内容定义了编译器知道的外部(您也可以添加自己的外部)。 webgl.jsw3c_indexeddb.js 都使用名为 get 的属性定义类型(WebGLContextAttributesIDBObjectStore分别)。默认情况下,编译器不知道 myClassthis 的类型,因此就其所知,this 可以引用以下实例: WebGLContextAttributesIDBObjectStore,在这种情况下,重命名 get 是不安全的。

通过使用类型注释(例如 @constructor)和编译器选项(例如 ambiguatePropertiesdisambiguateProperties)的组合,编译器可以确定 this 将始终引用 myClass 的新实例,并将其所有引用一致重命名为 get。您可以在Closure:权威指南的第14章中阅读有关这些编译器优化的更多信息。

I cannot duplicate your problem. If I go to http://closure-compiler.appspot.com/home and compile the following:

// ==ClosureCompiler==
// @compilation_level ADVANCED_OPTIMIZATIONS
// @output_file_name default.js
// ==/ClosureCompiler==

var myClass = function() {
  this["myFunc"] = this.myFunc;
  this["myFunc2"] = this.myFunc2;
};
window["myClass"] = myClass;

myClass.prototype = {
  myFunc: function() { alert("myFunc"); },
  myFunc2: function() { alert("myFunc2"); }
};

Then I get the following result:

function a(){this.myFunc=this.a;this.myFunc2=this.b}window.myClass=a;a.prototype={a:function(){alert("myFunc")},b:function(){alert("myFunc2")}};

The properties are renamed, as expected.

As for your second example, it has to do with a Closure Compiler concept known as externs. An extern is a symbol that will be predefined in the environment in which the JavaScript will run, such as window or document in the case of Web programming. Because such names are fixed in the environment, the Compiler cannot mangle these names.

If you look at the DEFAULT_EXTERNS_NAMES list in CommandLineRunner.java, you will see a list of files from the externs folder. The contents of these files define the externs that the Compiler knows about (you can also add your own externs). Both webgl.js and w3c_indexeddb.js define types with a property named get (WebGLContextAttributes and IDBObjectStore, respectively). By default, the Compiler does not know the type of this in myClass, so as far as it knows, this could refer to an instance of either WebGLContextAttributes or IDBObjectStore, in which case it would not be safe to rename get.

By using a combination of type annotations (such as @constructor) and Compiler options such as ambiguateProperties and disambiguateProperties, the Compiler can determine that this will always refer to a new instance of myClass and rename all of its references to get consistently. You can read more about these Compiler optimizations in Chapter 14 of Closure: The Definitive Guide.

时光匆匆的小流年 2024-11-25 22:27:04

此处的示例来看,您似乎需要在构造函数之外显式导出原型方法:

var myClass = function() {};
myClass.prototype = {
    myFunc: function() { alert("myFunc"); },
    myFunc2: function() { alert("myFunc2"); }
};

window["myClass"] = myClass;
myClass.prototype["myFunc"] = myClass.prototype.myFunc;
myClass.prototype["myFunc2"] = myClass.prototype.myFunc2;

这似乎像宣传的那样工作,尽管对我来说这似乎是一个奇怪的优化(所有重复的“原型”引用都会添加很多字节):

function a(){}a.prototype={a:function(){alert("myFunc")},
b:function(){alert("myFunc2")}};
window.myClass=a;
a.prototype.myFunc=a.prototype.a;
a.prototype.myFunc2=a.prototype.b;

From the example here, it looks like you need to explicitly export prototype methods outside of the constructor:

var myClass = function() {};
myClass.prototype = {
    myFunc: function() { alert("myFunc"); },
    myFunc2: function() { alert("myFunc2"); }
};

window["myClass"] = myClass;
myClass.prototype["myFunc"] = myClass.prototype.myFunc;
myClass.prototype["myFunc2"] = myClass.prototype.myFunc2;

This seems to work as advertised, though it seems like an odd optimization to me (all the repeated "prototype" references add a lot of bytes):

function a(){}a.prototype={a:function(){alert("myFunc")},
b:function(){alert("myFunc2")}};
window.myClass=a;
a.prototype.myFunc=a.prototype.a;
a.prototype.myFunc2=a.prototype.b;
甜柠檬 2024-11-25 22:27:04

原因是,通过 ADVANCED_OPTIMIZATIONS,GCC 对待 myObject["a"] 的方式与 myObject.a 不同。尝试以下操作:

var myObject = {};
myObject.attr1 = 3;
myObject["attr2"] = 4;
window["myObject"] = myObject;

它将编译为此,并使用 ADVANCED_OPTIMIZATIONS:

window.myObject={a:3,attr2:4};

我想您会看到现在需要做什么。

The reason is that, with ADVANCED_OPTIMIZATIONS, the GCC treats myObject["a"] differently from myObject.a. Try the following:

var myObject = {};
myObject.attr1 = 3;
myObject["attr2"] = 4;
window["myObject"] = myObject;

It will compile to this, with ADVANCED_OPTIMIZATIONS:

window.myObject={a:3,attr2:4};

I think you'll see what you need to do now.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文