首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Typescript和Google闭包

Typescript和Google闭包
EN

Stack Overflow用户
提问于 2012-11-30 06:26:19
回答 2查看 4.1K关注 0票数 4

我使用Typescript命令(tsc)创建一个包含所有plateform类的Javascript文件。

代码语言:javascript
复制
tsc "./Main.ts" -out "./script/myProject_debug.js" --declarations

然后,我想用谷歌闭包(compiler.jar)来混淆这个文件,如下所示:

代码语言:javascript
复制
java -jar ./compiler/compiler.jar --compilation_level ADVANCED_OPTIMIZATIONS --js "./script/myProject_debug.js" > "./script/myProject.js".

但是,当我执行产生的模糊/优化代码时,我得到了以下错误:未捕获原型:无法读取未定义的属性‘TypeError’

它匹配以下未混淆的JS代码(由tsc命令生成):

代码语言:javascript
复制
var __extends = this.__extends || function (d, b) {
    function __() { this.constructor = d; }
    __.prototype = b.prototype;
    d.prototype = new __();
}

此部分用于翻译“扩展”Typescript关键字,b的等价物是未定义的。

有没有人遇到过类似的错误或者/并且得到了一个解决方案,可以用一个Typescript编译的文件来混淆Google闭包?

我尝试使用uglifyjs命令,输出文件运行良好,但我希望完全混淆(类、参数、变量、方法等)。此外,Google Closure提供的额外优化将是受欢迎的。

谢谢你!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-12-01 21:32:40

好了,我找到问题所在了。

正如我前面所说的,b在中是未定义的:

代码语言:javascript
复制
var __extends = this.__extends || function (d, b) {
   function __() { this.constructor = d; }
   __.prototype = b.prototype;
   d.prototype = new __();
}

当typescript“编译”到javascript中时,如果您通过项目获得了一个名称空间,但是您将与此名称空间相关的所有类都写在单独的文件中,则Typescript将在最终生成的js文件中执行以下操作:

代码语言:javascript
复制
var namespace;
(function (namespace) {

    var Class1 = (function (dependency) {
        [...]
        return Class1;
    })(namespace.dependency);

    namespace.Class1 = Class1;
})(namespace || (namespace= {}));

var namespace;
(function (namespace) {

    var Class2 = (function (dependency) {
        [...]
        return Class2;
    })(namespace.dependency);

    namespace.Class2 = Class2;
})(namespace || (namespace= {}));

var namespace;
(function (namespace) {

    var Main = (function (dependency) {
        [...]
        return Main;
    })(namespace.Class2);

    namespace.Main = Main;
})(namespace || (namespace= {}));

我不知道它是如何工作的,但是google-closure-compiler删除了一些类,即使这段代码没有问题,JS可以处理它。因此,一些依赖项丢失,并且b未定义。

所以我发现,如果你像下面这样声明你的命名空间,你就不会再遇到这个错误了(只要使用了"Main“类,或者你在全局窗口对象中保留了命名空间的引用,闭包就会将所有的类保存在最终的混淆js文件中):

代码语言:javascript
复制
var namespace;
(function (namespace) {

    var Class1 = (function (dependency) {
        [...]
        return Class1;
    })(namespace.dependency);

    namespace.Class1= Class1;

    var Class2 = (function (dependency) {
        [...]
        return Class2;
    })(namespace.dependency);

    namespace.Class2= Class2;

    var Main = (function (dependency) {
        [...]
        return Main;
    })(namespace.Class2);

    namespace.Main = Main;
})(namespace || (namespace= {}));

我想我会在typescriptlang.org上打开一个问题。顺便说一句,它正在优化生成的文件大小。

感谢您的回答!

票数 0
EN

Stack Overflow用户

发布于 2012-11-30 22:35:23

__extends的定义有一个问题,这很可能导致您看到的错误。

代码语言:javascript
复制
var __extends = this.__extends || function (d, b) { ... };

this.__extends引用应该和window.__extends是一样的,但是闭包编译器不知道(甚至不会尝试)意识到在全局上下文中对this的引用实际上是window对象。使用--warning_level=VERBOSE编译时,编译器将发出以下警告:

代码语言:javascript
复制
Dangerous use of the global this object at line 1 character 16
var __extends = this.__extends || function (d, b) {
                ^

此外,this.__extends是对外部/未定义属性的引用,编译器也在VERBOSE级别上对此发出警告。

我已经修改并注释了定义,以便使用Closure-compiler Service UI编译时不会出现警告。

代码语言:javascript
复制
// ==ClosureCompiler==
// @compilation_level ADVANCED_OPTIMIZATIONS
// @warning_level VERBOSE
// @output_file_name default.js
// @formatting pretty_print
// ==/ClosureCompiler==

var __extends = window['__extends'] || function (d, b) {
  /** @constructor */
  function __() { this.constructor = d; }
  __.prototype = b.prototype;
  d.prototype = new __();
}

/**
 * @constructor
 * @extends {String}
 */
function foo2() {this.foo = 'bar'; }
__extends(foo2, String);

var bar2 = new foo2;
alert(bar2.toLowerCase);

A JSFiddle of the modified and compiled code

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13635901

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档