Что вызывает ошибку «Невозможно выполнить код из освобожденного скрипта» - PullRequest
61 голосов
/ 17 сентября 2008

Я думал, что нашел решение некоторое время назад (см. Мой блог ):

Если вы когда-нибудь получили ошибку JavaScript (или должна быть JScript) «Не удается выполнить код из освобожденного скрипта» - попробуйте переместить любые метатеги в голове так, чтобы они были перед вашими тегами скрипта.

... но, основываясь на одном из последних комментариев в блоге, предложенное мной исправление может работать не для всех. Я подумал, что это было бы хорошо, чтобы открыть для сообщества StackOverflow ....

Что вызывает ошибку «Невозможно выполнить код из освобожденного скрипта» и каковы решения / обходные пути?

Ответы [ 13 ]

33 голосов
/ 17 сентября 2008

Вы получаете эту ошибку, когда вызываете функцию, которая была создана в окне или кадре, который больше не существует.

Если вы заранее не знаете, существует ли окно, вы можете попробовать / поймать его, чтобы обнаружить:

try
{
  f();
}
catch(e)
{
  if (e.number == -2146823277)
    // f is no longer available
    ...
}
19 голосов
/ 17 сентября 2008

Звучит так, как будто вы столкнулись с ошибкой / проблемой в том, как обрабатываются некоторые теги, или что у вас есть ссылки на освобожденные объекты, для которых вы пытаетесь выполнить методы.

Сначала я бы переместил любые теги <meta> перед любыми тегами <script>, как это было предложено здесь и во многих других местах.

Затем проверьте, обсуждались ли у вас проблемы со страницей / безопасностью здесь .

18 голосов
/ 01 сентября 2009

Ошибка возникает, когда «родительское» окно сценария расположено (т.е. закрыто), но вызывается ссылка на сценарий, который все еще удерживается (например, в другом окне). Даже если «объект» все еще жив, контекст, в котором он хочет выполнить, отсутствует.

Это немного грязно, но работает для моего гаджета Windows Sidebar:

Вот общая идея: «Главное» окно устанавливает функцию, которая будет оценивать некоторый код, да, это так ужасно. Затем «потомок» может вызвать эту «функцию строителя» (которая / связана с областью главного окна) и вернуть функцию, которая также связана с «главным» окном. Очевидным недостатком является, конечно, то, что функция «отскока» не может быть закрыта по объему, в котором она, казалось бы, определена ... в любом случае, достаточно гибкости:

Это частично псевдокод, но я использую его вариант в гаджете боковой панели 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.

8 голосов
/ 25 февраля 2014

Если вы пытаетесь получить доступ к объекту JS, самый простой способ - создать копию:

var objectCopy = JSON.parse(JSON.stringify(object));

Надеюсь, это поможет.

6 голосов
/ 11 мая 2010

Вот очень специфический случай, в котором я видел такое поведение. Это воспроизводимо для меня в IE6 и IE7.

Изнутри фрейма:

window.parent.mySpecialHandler = function() { ...work... }

Затем, после перезагрузки iframe с новым содержимым, в окне, содержащем iframe:

window.mySpecialHandler();

Этот вызов завершается с ошибкой «Не удается выполнить код из освобожденного сценария», поскольку mySpecialHandler был определен в контексте (исходном DOM iframe), который больше не завершается. (Перезагрузка iframe уничтожила этот контекст.)

Однако вы можете безопасно устанавливать «сериализуемые» значения (примитивы, графы объектов, которые не ссылаются на функции напрямую) в родительском окне. Если вам действительно нужно отдельное окно (в моем случае, iframe), чтобы указать какую-то работу для удаленного окна, вы можете передать эту работу как String и «оценить» ее в получателе. Будьте осторожны с этим, как правило, это не делает для чистой или безопасной реализации.

5 голосов
/ 12 июля 2011

Начиная с IE9, мы начали получать эту ошибку при вызове .getTime () для объекта Date, хранящегося в массиве в другом объекте. Решением было убедиться, что это Date, прежде чем вызывать методы Date:

Ошибка: rowTime = wl.rowData[a][12].getTime()

Пропуск: rowTime = new Date(wl.rowData[a][12]).getTime()

5 голосов
/ 17 сентября 2008

Эта ошибка может возникнуть в MSIE, когда дочернее окно пытается связаться с родительским окном, которое больше не открыто.

(Не совсем самый полезный текст сообщения об ошибке в мире.)

2 голосов
/ 30 мая 2013

Я столкнулся с этой проблемой, когда внутри дочернего кадра я добавил ссылочный тип в окно верхнего уровня и попытался получить к нему доступ после перезагрузки дочернего окна

т.е.

// 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());
1 голос
/ 29 апреля 2012

Это на самом деле не ответ, а скорее пример того, где именно это и происходит.

У нас есть кадр A и кадр B (это была не моя идея, но я должен жить с этим). Кадр А никогда не меняется, Кадр Б постоянно меняется. Мы не можем применить изменения кода непосредственно к кадру A, поэтому (согласно инструкциям поставщика) мы можем запустить JavaScript только в кадре B - точном кадре, который постоянно изменяется.

У нас есть фрагмент JavaScript, который должен запускаться каждые 5 секунд, поэтому JavaScript в кадре B создает новый тег сценария и вставляет его в заголовочный раздел кадра B. В этих новых сценариях существует setInterval (тот, который вставлен ), а также функция для вызова. Несмотря на то, что введенный JavaScript-код технически загружается фреймом A (поскольку теперь он содержит тег script), после изменения фрейма B функция setInterval больше не доступна.

0 голосов
/ 14 октября 2018

Объяснения очень актуальны в предыдущих ответах. Просто пытаюсь представить свой сценарий. Надеюсь, что это может помочь другим.

мы использовали:

<script> window.document.writeln(table) </script>

и вызов других функций в сценарии при onchange событиях, но writeln полностью переопределяет HTML в IE, где он ведет себя по-разному в chrome.

мы изменили его на:

<script> window.document.body.innerHTML = table;</script> 

Таким образом сохранил скрипт, который исправил проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...