eval JS在AJAX中加载了内容

时间:2013-06-22 13:11:02

标签: javascript ajax

我想在另一个页面中通过XMLHttpRequest加载此代码(1)

<input type="text" onkeypress="info(event)"/>
<script>
  function info(e) { console.log(e.keyCode); }
</script>

这是(2)我试过的方式......

<div id="x"></div>
<script>
  var xhr = new XMLHttpRequest();
  xhr.onload = handleResponse.bind(xhr);
  xhr.open("POST","test.php",true);
  xhr.send();

  function handleResponse() {
    var x = document.getElementById("x");
    x.innerHTML = this.responseText;
    var js = x.getElementsByTagName("script")[0];
    eval(js.innerText);
  }
</script>

...这是我在按键时遇到的错误:

Uncaught ReferenceError: info is not defined

为什么找不到info(),因为它的定义是eval'd?如果(2)应该不知道(1),如何在按键上触发信息?没有jQuery。

根据迈克的建议,我创建了this question来解决导致解释此问题的分离问题。

1 个答案:

答案 0 :(得分:1)

范围。你没有在window上评估它,你将它添加到该函数handleResponse的范围内,因此它不会存在于handleResponse之外。此外,在这种情况下,你根本不需要eval。就这样做:

function handleResponse() {
  var x = document.getElementById("x");
  x.innerHTML = this.responseText;
  // grab all script elements, as an array
  // (rather than document.queryS..'s NodeList answer)
  var js = [].slice.call( x.querySelectorAll("script"), 0);
  // add all those scripts to the head element
  js.forEach(function(scriptElement) {
    document.head.appendChild(scriptElement);
    // this moves the script element from [x] to [head]
  });
}

浏览器已经知道如何解释脚本,但如果您希望它们执行而不是作为非活动DOM节点插入,则需要向head添加元素。

最后,如果你真的需要eval(由于上述原因,你有99.99%的时间不这样做),使用new Function要好得多,因为这样你就可以捕获语法和运行时错误,而不是做“谁知道什么”:

try {
  var evaluator = new Function("return " + js.innerText + ";");
  try {
    evaluator();
  } catch (runtimeError) {
    console.log("ERROR: eval'd code is legal, but runtime-broken");
  }
} catch (syntaxError) {
  console.log("ERROR: js.innerText has syntax errors");
}