【问题标题】:Haxe for javascript without global namespace pollution?Haxe for javascript 没有全局命名空间污染?
【发布时间】:2010-09-30 06:52:21
【问题描述】:

此问题仅适用于 Haxe 版本

我知道 haxe 有一段时间了,但直到昨天才真正玩过它。出于好奇,我决定将showdown.jsmarkdown.pl 的 javascript 端口)移植到 haxe。这非常简单,它生成的 javascript 似乎运行良好(编辑:如果你想看到它的实际效果,请查看here)。

但是,我注意到生成的代码会在全局命名空间中转储大量内容...更糟糕的是,它通过将值分配给 未声明的标识符 而不使用 var 关键字来实现,所以即使你用闭包包裹整个东西,它们也是全局的。

例如...

if(typeof js=='undefined') js = {}
...
Hash = function(p) { if( p === $_ ) return; {
...
EReg = function(r,opt) { if( r === $_ ) return; {
...

我设法用 sed 清理了大部分内容,但我也被这样的事情困扰:

{
 String.prototype.__class__ = String;
 String.__name__ = ["String"];
 Array.prototype.__class__ = Array;
 Array.__name__ = ["Array"];
 Int = { __name__ : ["Int"]}
 Dynamic = { __name__ : ["Dynamic"]}
 Float = Number;
 Float.__name__ = ["Float"];
 Bool = { __ename__ : ["Bool"]}
 Class = { __name__ : ["Class"]}
 Enum = { }
 Void = { __ename__ : ["Void"]}
}
{
 Math.__name__ = ["Math"];
 Math.NaN = Number["NaN"];
 Math.NEGATIVE_INFINITY = Number["NEGATIVE_INFINITY"];
 Math.POSITIVE_INFINITY = Number["POSITIVE_INFINITY"];
 Math.isFinite = function(i) {
  return isFinite(i);
 }
 Math.isNaN = function(i) {
  return isNaN(i);
 }
}

这是一些非常令人讨厌的 javascript。


问题

在不会污染全局变量的地方是否有一个分叉或克隆的 haxe?修改haxe源以获得我想要的东西是否值得,或者已经有人解决了这个问题?谷歌搜索并没有出现太多。我愿意接受任何建议。同时,我很想看看这个东西会产生什么样的 PHP 代码...... :D


答案?

以下是我尝试过的一些想法:

后处理

这是我简陋的构建脚本;它在剥离东西方面做得很好,但它并不能捕捉到所有东西。我犹豫是否要删除对内置构造函数原型的修改;我敢肯定这会破坏事情。解决所有问题可能是一项艰巨的任务,如果有人已经完成了工作,我不想开始...

haxe -cp ~/Projects/wmd-new -main Markdown -js markdown.js

echo "this.Markdown=(function(){ var \$closure, Float;" > markdown.clean.js;

sed "s/^if(typeof js=='undefined') js = {}$/if(typeof js=='undefined') var js = {};/g ;
     s/^\([ \x09]*\)\([\$_a-zA-Z0-9]* = \({\|function\)\)/\1var \2/g ;
      /^[ \x09]*\(else \)\?null;$/d ;
     " markdown.js >> markdown.clean.js

echo "return Markdown}());" >> markdown.clean.js;

java -jar closure/compiler.jar --js markdown.clean.js \
--compilation_level SIMPLE_OPTIMIZATIONS \
> markdown.cc.js

--js-namespace 开关节省时间

感谢 Dean Burge 指出命名空间切换。这几乎解决了我的问题,并提供了一点帮助。这是我当前的构建脚本。我认为这会捕获所有全局变量...

NS=N\$

haxe -cp ~/Projects/wmd-new -main Markdown --js-namespace $NS -js markdown.js 

# export our function and declare some vars
echo "this.markdown=(function(){var \$_,\$Main,\$closure,\$estr,js,"$NS"" > markdown.clean.js;

# strip silly lines containing "null;" or "else null;"
sed "/^[ \x09]*\(else \)\?null;$/d ;" markdown.js >> markdown.clean.js

# finish the closure
echo "return "$NS".Markdown.makeHtml}());" >> markdown.clean.js;

【问题讨论】:

  • 自 haxe 2.10 起,此问题不再相关。试试try.haxe.org/#1cf90
  • @CésarAlforde 为什么这个问题不再相关?
  • 因为从haxe 2.10开始,所有生成的代码都被封装在一个匿名函数中,所以没有全局命名空间污染,和从coffeescript脚本中得到的一样。

标签: javascript global-variables haxe


【解决方案1】:

我使用namespace switch on the compiler 来清理那些全局根类型。

【讨论】:

  • 这解决了我关心的大部分问题。仍然存在一些未声明的全局变量; $_$Main$closure$estrjs 和用户定义的命名空间是我找到的。这可以通过在闭包开始时声明变量来轻松解决,尽管
  • 我刚刚发现有人为此提交了一个错误:code.google.com/p/haxe/issues/detail?id=214
【解决方案2】:

Haxe 并非用于在 javascript Web 应用程序中编写隔离的可重用组件。编译器为每个该死的编译都发出标准库这一事实证明了这一点。 javascript 目标的最佳使用是完全用 haxe 编写应用程序,并使用无类型块调用外部内容,希望它不会破坏任何东西。您应该将 haxe 输出视为 Flash 剪辑,忽略它运行的环境,假设它是唯一运行的东西。

或者您可以尝试使用 with() 块包装代码。

【讨论】:

  • 感谢您的回复。如果我不是在编写一个孤立的可重用组件,那么就我而言,我正在编写垃圾。不过,我仍然有一些想法。顺便说一句,我在 with block 的事情上大笑……我希望那是个笑话 :)
  • 顺便说一句,haxetacy 有一个可以将类拆分成文件的后编译器:code.google.com/p/haxetacy/wiki/postcompiler
  • 我不想将它们拆分成文件,我只是想避免任何我没有专门导出的全局变量。
【解决方案3】:

这里有一个命名空间(实验性)haxe 编译器http://github.com/webr3/haxe

【讨论】:

  • 快速浏览了一下,但我不确定这就是我想要的...不过还是谢谢。
【解决方案4】:

JSTM JavaScript 生成器宏以多种方式优化 haxe 输出:

  1. javascript 输出按类型拆分为单独的文件
  2. 这些文件已经过优化
  3. 加载器脚本异步加载所需类型
  4. 只使用了一个全局变量:jstm
  5. 仅下载运行您的应用实际需要的代码
  6. 可以在运行时加载新类型,从而实现高度可扩展的应用程序

查看http://code.google.com/p/jstm/ 了解更多信息。

【讨论】:

    猜你喜欢
    • 2014-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-15
    • 2011-06-16
    • 1970-01-01
    • 2012-02-10
    • 1970-01-01
    相关资源
    最近更新 更多