我以为我不久前找到了解决方案(请参阅我的博客):
如果您遇到 JavaScript(或者应该是 JScript)错误“无法从已释放的脚本中执行代码” - 请尝试移动头部中的任何元标记,以便它们位于您的脚本标记之前。
...但是根据最近的博客评论之一,我建议的修复可能不适用于所有人。我认为这将是一个向 StackOverflow 社区开放的好方法......
什么导致错误“无法从释放的脚本执行代码”以及解决方案/解决方法是什么?
我以为我不久前找到了解决方案(请参阅我的博客):
如果您遇到 JavaScript(或者应该是 JScript)错误“无法从已释放的脚本中执行代码” - 请尝试移动头部中的任何元标记,以便它们位于您的脚本标记之前。
...但是根据最近的博客评论之一,我建议的修复可能不适用于所有人。我认为这将是一个向 StackOverflow 社区开放的好方法......
什么导致错误“无法从释放的脚本执行代码”以及解决方案/解决方法是什么?
当您调用在不再存在的窗口或框架中创建的函数时,您会收到此错误。
如果你事先不知道窗口是否仍然存在,你可以做一个 try/catch 来检测它:
try
{
f();
}
catch(e)
{
if (e.number == -2146823277)
// f is no longer available
...
}
该错误是在脚本的“父”窗口被释放(即:关闭)但调用对仍然持有的脚本的引用(例如在另一个窗口中)时引起的。即使“对象”还活着,它想要执行的上下文也不是。
它有点脏,但它适用于我的 Windows 边栏小工具:
这是一般的想法:“主”窗口设置了一个函数,它将评估一些代码,是的,它就是那么难看。然后一个“孩子”可以调用这个“构建器函数”(它/绑定到主窗口的范围/)并取回一个也绑定到“主”窗口的函数。当然,一个明显的缺点是,被“反弹”的函数不能在它看似定义的范围内关闭......无论如何,足够的胡言乱语:
这部分是伪代码,但我在 Windows 边栏小工具上使用了它的一个变体(我一直这么说是因为边栏小工具在“不受限制的区域 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)来为远程窗口指定一些工作,你可以将工作作为字符串传递并在接收器中“评估”它。请注意这一点,它通常不会带来干净或安全的实现。
如果您尝试访问 JS 对象,最简单的方法是创建一个副本:
var objectCopy = JSON.parse(JSON.stringify(object));
希望它会有所帮助。
当子窗口尝试与不再打开的父窗口通信时,MSIE 中可能会发生此错误。
(不完全是世界上最有用的错误消息文本。)
从 IE9 开始,当对存储在另一个对象的数组中的 Date 对象调用 .getTime() 时,我们开始收到此错误。解决方案是在调用 Date 方法之前确保它是 Date :
失败:rowTime = wl.rowData[a][12].getTime()
经过:rowTime = new Date(wl.rowData[a][12]).getTime()
我在子框架内遇到了这个问题,我向顶层窗口添加了一个引用类型,并在子窗口重新加载后尝试访问它
IE
// set the value on first load
window.top.timestamp = new Date();
// after frame reloads, try to access the value
if(window.top.timestamp) // <--- Raises exception
...
我能够通过仅使用原始类型来解决问题
// set the value on first load
window.top.timestamp = Number(new Date());
这并不是一个真正的答案,而是更多的例子来说明这种情况究竟发生在哪里。
我们有框架 A 和框架 B(这不是我的想法,但我必须接受它)。框架 A 永不改变,框架 B 不断变化。我们不能将代码更改直接应用到框架 A,因此(根据供应商的说明)我们只能在框架 B 中运行 JavaScript——即不断变化的确切框架。
我们有一段 JavaScript 需要每 5 秒运行一次,因此框架 B 中的 JavaScript 创建一个新的脚本标签并插入到框架 B 的头部部分。 setInterval 存在于这个新脚本(注入的那个)中,如以及要调用的函数。尽管注入的 JavaScript 在技术上是由帧 A 加载的(因为它现在包含脚本标记),但一旦帧 B 更改,setInterval 将无法再访问该函数。
我在最终打开 iFrame 的页面中的 IE9 中遇到此错误。只要 iFrame 没有打开,我就可以使用 localStorage。打开和关闭 iFrame 后,由于此错误,我无法再使用 localStorage。要修复它,我必须将此代码添加到 iFrame 内部的 Javascript 中,并使用 localStorage。
if (window.parent) {
localStorage = window.parent.localStorage;
}
打开对话时在 DHTMLX 中出现此错误,找不到父 ID 或当前窗口 ID
$(document).ready(function () {
if (parent.dxWindowMngr == undefined) return;
DhtmlxJS.GetCurrentWindow('wnManageConDlg').show();
});
只需确保在打开对话时发送正确的当前/父窗口 ID
在更新 iframe 的 src 时,我收到了该错误。
通过像这样访问主窗口中元素的事件(在我的情况下单击)得到该错误(直接调用主/最外窗口):
top.$("#settings").on("click",function(){
$("#settings_modal").modal("show");
});
我只是像这样更改它并且它工作正常(调用 iframe 窗口的父级的父级):
$('#settings', window.parent.parent.document).on("click",function(){
$("#settings_modal").modal("show");
});
我的包含模态框的 iframe 也在另一个 iframe 中。
前面的答案中的解释非常相关。只是想提供我的场景。希望这可以帮助其他人。
我们正在使用:
<script> window.document.writeln(table) </script>
, 并在事件中调用脚本中的其他函数,onchange
但 writeln 完全覆盖了 IE 中的 HTML,因为它在 chrome 中具有不同的行为。
我们将其更改为:
<script> window.document.body.innerHTML = table;</script>
因此保留了解决问题的脚本。