导致错误"无法从释放的脚本执行代码"的原因是什么
我以为我早就找到了解决方案(请参阅我的博客):
If you ever get the JavaScript (or should that be JScript) error "Can't execute code from a freed script" - try moving any meta tags in the head so that they're before your script tags.
...但是根据最近的博客评论之一,我建议的修复可能并不适合所有人。我认为这是向StackOverflow社区开放的好人...。
是什么原因导致错误"无法从释放的脚本中执行代码",解决方案/解决方法是什么?
解决方案
回答
当子窗口尝试与不再打开的父窗口进行通信时,MSIE中可能会发生此错误。
(不完全是世界上最有用的错误消息文本。)
回答
听起来我们在处理某些标签的方式上遇到了错误/问题,或者我们引用了要在其上执行方法的已发布对象。
首先,我将所有<meta>
标签移到此处和许多其他地方建议的所有<script>
标签之前。
然后检查是否有此处讨论的页面/安全问题。
回答
当我们调用在不再存在的窗口或者框架中创建的函数时,会出现此错误。
如果我们事先不知道该窗口是否仍然存在,则可以尝试/捕获以检测到该窗口:
try { f(); } catch(e) { if (e.number == -2146823277) // f is no longer available ... }
回答
当脚本的"父"窗口被放置(即:关闭)但调用仍保留的脚本(例如在另一个窗口中)的引用时,会导致该错误。即使"对象"仍然存在,但它要执行的上下文却没有。
它有点脏,但是适用于我的Windows边栏小工具:
这是一般的想法:
"主"窗口设置了一个函数,该函数将评估一些代码,是的,这很丑陋。
然后,"子级"可以调用此"生成器函数"(/绑定到主窗口的范围/),并获得也绑定到"主"窗口的函数。当然,一个明显的缺点是,被"绑定"的函数无法关闭它似乎在...中定义的范围,无论如何,足够多的麻烦了:
这是部分伪代码,但是我在Windows Sidebar Gadget上使用了它的变体(我之所以这样说是因为Sidebar Gadgets在"不受限制的区域0"中运行,这可能会或者可能不会极大地改变方案。)
// This has to be setup from the main window, not a child/etc! mainWindow.functionBuilder = function (func, args) { // trim the name, if any var funcStr = ("" + func).replace(/^function\s+[^\s(]+\s*\(/, "function (") try { var rebuilt eval("rebuilt = (" + funcStr + ")") return rebuilt(args) } catch (e) { alert("oops! " + e.message) } } // then in the child, as an example // as stated above, even though function (args) looks like it's // a closure in the child scope, IT IS NOT. There you go :) var x = {blerg: 2} functionInMainWindowContenxt = mainWindow.functionBuilder(function (args) { // in here args is in the bound scope -- have at the child objects! :-/ function fn (blah) { return blah * args.blerg } return fn }, x) x.blerg = 7 functionInMainWindowContext(6) // -> 42 if I did my math right
作为变体,只要在主窗口上下文中定义了functionBuilder函数,主窗口就应该能够将functionBuilder函数传递给子窗口!
我觉得我说的话太多了。 YMMV。
回答
这是一个非常特殊的情况,在这种情况下,我已经看到了这种行为。对我来说,它在IE6和IE7中是可复制的。
在iframe中:
window.parent.mySpecialHandler = function() { ...work... }
然后,在用新内容重新加载iframe之后,在包含iframe的窗口中:
window.mySpecialHandler();
此调用失败,并显示"无法从释放的脚本执行代码",因为mySpecialHandler是在不再存在的上下文(iframe的原始DOM)中定义的。 (重新加载iframe会破坏此上下文。)
但是,我们可以在父窗口中安全设置"可序列化"的值(基元,不直接引用函数的对象图)。如果我们确实需要一个单独的窗口(在我的情况下为iframe)来指定一些工作到远程窗口,则可以将工作作为String传递,并在接收器中"评估"它。对此要小心,它通常无法实现干净或者安全的实现。