2011-08-03 3 views
1

Ajax 호출을 사용하여 일부 JavaScript를 String으로 가져 왔습니다. onSuccess 메소드에서이 코드를 평가하고 싶습니다. JavaScript 코드에는 함수 선언이 있습니다. 이러한 모든 기능은 평가 이후에 액세스 할 수 있어야합니다.범위와 평가 설명

나는 가능한 한 작은 예를 만들었습니다. (JFiddle에서는 성공적인 Ajax 호출을 만들 수 없으므로 예제의 onFailure 메서드에서 문제가 발생합니다.)

는 여기에서 예를 찾을 수 있습니다 http://jsfiddle.net/ubXAV/6/

모든 브라우저에서 작동하고 볼 수있는 예 (불행하게도,이 IE에서 JSFiddle에서 작동하지 않습니다). 나는 아래의 질문을 언급하는 몇 줄을 표시했다. 여기에 코드를 다시입니다 :

function evalScript(script) 
{ 
    that.eval(script); //1. 
} 

var that = this; 

// AJAX-Call - GadgetActionServlet 
new Ajax.Request("THISWILLFAIL.com", { 
    method: 'post', 
    onSuccess: function(ajaxResponse) { 
      alert("success"); 
    }, 
    onFailure: function(){ 
     var script = "{function sayHello(){alert('Hello');}}"; 
     //that.eval(script); //not working in IE 2. 
     evalScript(script); //working in all browsers 
    } 
}); 

내가 자바 범위 및 컨텍스트에 대한 인터넷에 많이 읽을 수 있지만 난 그냥 여기에 행동을 설명 할 수 없다 : 나는 평가 호출해야 할 이유

  1. 을 에 "그"? 인터넷에서 많은 정보원에 따르면 전 세계적으로 정의 된 기능의 맥락은 가장 글로벌 한 맥락입니다. (여기에 창이 있어야합니다). 그리고 eval을 통해 평가 된 코드는 eval 함수를 호출하는 컨텍스트에서 실행되어야합니다.

  2. Ajax 호출에 대한 새로운 글로벌 컨텍스트가 있다고 가정하면 (즉,?) 왜 evalScript 함수에 액세스 할 수 있지만 여기서 직접 스크립트를 평가할 수는 없습니다.

내가 가진 전반적인 질문은 다음과 같습니다. 어떤 규칙이 eval 사용에 적용됩니까? 컨텍스트와 관련된 내 기능은 어디에 있습니까? 그리고 : 예제에서와 같이 프로토 타입 Ajax 호출에는 자체 전역 객체가 있습니까?

+1

jsFiddle에서 실제로 AJAX 호출을 성공적으로 수행 할 수 있습니다.이 [참조 페이지] (http://doc.jsfiddle.net/use/echo.html)를 참조하십시오. –

+0

단어 'I'는 영어로 대문자로 표기됩니다. –

답변

4

먼저 도움이 될 것입니다 생각 오프 : 당신이 eval을 사용하지 않는 경우, eval을 사용하지 마십시오. 코드 POST에서 돌아 오는이 있습니까? 대신 GET를 사용하고자하는 경우 때문에, 당신은 단지 페이지에 스크립트 요소를 추가 할 수 있습니다 : 완료

var script = document.createElement('script'); 
script.src = "http://example.com" + 
       "?" + encodeURIComponent("param1name") + "=" + encodeURIComponent("param1value") + 
       "&" + encodeURIComponent("param1name") + "=" + encodeURIComponent("param2value"); 
var parent = document.body 
      || document.documentElement 
      || document.getElementsByTagName('head')[0]; 
parent.appendChild(script); 

합니다.

POST이어야한다면 은 실제 스크립트 코드 여야합니까? 의 데이터가 페이지 상에 이미 코드로으로 해석 될 수 없습니까? JSON은 유용한 데이터 형식입니다. 그것은 POST로, 그리고 당신이 돌아 을 가지고하는 데이터와 달리 실제 스크립트 코드로이있는 경우

그러나, 우리는 eval처럼 뭔가를해야 할 것이다. :-)

eval 자체는 매우 특별합니다. 함수처럼 보이지만 함수가 작동하는 방식이 아니더라도 사용 된 범위 내에서 작동합니다.따라서 eval 호출이 실제로 전역 범위 (어떤 함수 호출도 포함되지 않음)에서 이 아니고 여기에서 수행 할 수없는 경우에는 실제로 전역 범위에서 스크립트 코드를 평가하는 것이 어렵습니다.   — 아약스 콜백에서 이것을 트리거해야합니다 , 정의상 이것은 함수 내에서 발생합니다. (편집 :. 난 그냥 실제로 함수 내에서 전역 범위에서 eval를 사용할 수있는 대답의 끝에서 업데이트를 참조하는 방법을 생각하지만 사악하고 끔찍한 잘못입니다..)

이유 당신에게 window.eval을 사용하라는 조언을 보았을 수도 있습니다. 많은 현대의 브라우저는 글로벌 범위에서 주어진 코드를 평가하는 (eval과 반대)을 제공합니다. 하지만 모든 브라우저에서 사용할 수있는 것은 아니며 오래된 브라우저는 아닙니다.

그러나 해결 방법이 있습니다. IE 제품군은 다른 브라우저에서 제공하는 window.eval과 비슷한 매우execScript을 제공하며 최악의 경우 script 요소를 사용하여 다시 사용할 수 있습니다.

window.evalInGlobalScope = (function() { 
    var fname, scr; 

    // Get a unique function name 
    do { 
     fname = "__eval_in_global_test_" + Math.floor(Math.random() * 100000); 
    } 
    while (typeof window[fname] !== 'undefined'); 

    // Create test script 
    scr = "function " + fname + "() { }"; 

    // Return the first function that works: 
    return test(evalInGlobalScope_execScript) || 
      test(evalInGlobalScope_windowEval) || 
      test(evalInGlobalScope_theHardWay) || 
      evalInGlobalScope_fail; 

    function test(f) { 
     try { 
      f(scr); 
      if (typeof window[fname] === 'function') { 
       return f; 
      } 
     } 
     catch (e) { 
      return false; 
     } 
     finally { 
      try { delete window[fname]; } catch (e) { window[fname] = undefined; } 
     } 
    } 
    function evalInGlobalScope_execScript(str) { 
     window.execScript(str); 
    } 
    function evalInGlobalScope_windowEval(str) { 
     window.eval(str); 
    } 
    function evalInGlobalScope_theHardWay(str) { 
     var parent, script, d = document; 

     parent = d.body || d.documentElement || d.getElementsByTagName('head')[0]; 
     if (parent) { 
      script = d.createElement('script'); 
      script.appendChild(d.createTextNode(str)); 
      parent.appendChild(script); 
     } 
    } 
    function evalInGlobalScope_fail() { 
     throw "evalInGlobalScope: Unable to determine how to do global eval in this environment"; 
    } 
})(); 

.. 그리고 here's a live example of using it : 여기에 거의 모든 작동하는 글로벌 eval 함수입니다.

사용할 코드를 결정하는 코드는 모두 한 번만 실행됩니다. 선택한 기능은 windowevalInGlobalScope 속성에 할당됩니다.

또한 반환 값을 지정하지 않았습니다. 왜냐하면 "어려운 방법"버전은 기본적으로 반환 값을 반환 할 수 없기 때문에 버전 중 하나가 없으면 가장 안전합니다. 나도 알아, 난 아직도 "어려운 방법"을 필요로하는지 모르겠다   — 거의 모든 게 execScript 및/또는 window.eval 있습니다.


업데이트 : 나는 당신이 함수 내에서 전역 범위에서 eval를 사용하지 수있는 위 말했다. 그리고 기술적으로 그것은 사실이지만, 나는 그 주위를 끝내기위한 방법을 생각했습니다. 그것은 사악하고 끔찍한 잘못이지만,이 작업을 수행합니다 대신 사용 setTimeout, 그리고 그것을 0의 시간 제한 제공 : 당신이 문자열을 setTimeout 줄 때

setTimeout("your code here", 0); 

, 그것은 타임 아웃 후   —에 eval을 수행을, (글로벌 범위에서)

다시 말하지만, 그것은 악하고 끔찍한 것이고 잘못되었습니다. 우리의 evalInGlobalScope 함수를 사용하면 동기식으로 eval이 발생하지만 비동기식이라는 단점이 있습니다. (Live copy) I 을 권장하지 않습니다.

+0

그 위대한 답변에 감사드립니다! 그것은 내가 걸려 넘어지는 모든 나의 문제를 설명한다! – Chris