문제

다음과 같은 JavaScript 스 니펫을 감안할 때 :

var x = 10;

function sayx() {
  alert(x);
}

sayx();

물론 메시지 상자 인쇄 '10'을 기대할 수 있습니다. 'X'가 결정되는 방식과 상호 작용하기 위해 여러 기능 중첩을 수행 할 수 있습니다. X가 무엇인지 해결할 때 환경이 범위 체인을 올라가기 때문입니다.

런타임에 새 스코프를 주입하기 위해 Eval을 사용하여 '재 컴파일'레벨을 수행 할 수도 있습니다.

var x = 10;

function sayx() {
  alert(x);
}

function wrap(f) {
  return eval('(function() { var x = 20;(' + f + ')(); })');
}

wrap(sayx)();

이 기능은 '원본'소스를 반환 할 Tostring 함수가 호출되기 때문에 작동합니다. 따라서 본질적으로 X를 무시하는 새로운 스코프가있는 랩핑 된 기능을 만듭니다. 결과는 인쇄하는 경고 상자가됩니다. '10'이 아닌 '20'.

그러나 표면에서는 이것이 작동하는 것처럼 보일 수 있지만 스코프 체인이 고장 났고 체인의 다음 항목은 기능 'f'가 이제 다른 위치에서 정의되어 있기 때문에 더 이상 동일하지 않습니다. 상속은 호출 함수에 액세스 할 수 없다는 많은 참조를 포함 할 수 있습니다.

그렇다면 스코프 항목을 주입하는 더 지원적이고 실행 가능한 방법이 있습니까? 같은 것 :

function withScope(f, scope) { ??? }

---

var x = 10, y = 10;

function dothemath() {
  alert(x + y);
}

var haxthemath = withScope(dothemath, { x: 9000 });
haxthemath(); // 9010 not 20

나는 대답이 '아니오'라고 생각합니다. 어떤 사람들은 그러한 스코프 주입과 관련된 '보안'문제가 있다고 주장 할 수도 있지만, 어쨌든 당신이 어쨌든 트릭을 수행 할 수 있다고 생각하면 (심하게 깨 졌음) .. 나는 그것이 생각하지 않습니다.

이것의 이점은 본질적으로 자신의 의사 변수를 가짜로 만들 수 있다는 것입니다.

미리 감사드립니다.


편집, 조금 명확하게 설명하고, 다음 스코프 체인이있는 함수를 '과거'하고 싶다고 상상해보십시오.

Window - window properties
Object - { var x = 10 }
Object - { var y = 5 + x }

효과적으로 동일한 체인 +가 제공하는 범위를 갖는 함수를 되 찾을 수 있기를 원합니다.

withScope(somefunc, { foo: 'bar' })

나에게 줄 것이다

Window - window properties
Object - { var x = 10 }
Object - { var y = 5 + x }
Ext scope - { foo = 'bar' }

내 확장 된 범위가 그들에 대해 아무 말도하지 않기 때문에 모든 이전의 스탠딩 변수가 발견됩니다.

도움이 되었습니까?

해결책

기능 및/또는 폐쇄의 로컬 변수에 대한 범위를 참조하는 경우 답은 아니오라고 생각합니다.

당신은의 범위를 변경할 수 있습니다 this functionName.call (scope, arg1, ...) 또는 functionName.Apply (scope, [arg1, ...])를 사용하여 키워드; 이것은 프로토 타입과 함께 사용하여 설명하는 것과 유사한 체인을 만들 수 있습니다. 객체 자체의 특성에서 무언가를 찾을 수없는 경우 프로토 타입에서 찾아 섰습니다. 속성이 없으면 체인의 다음 프로토 타입이 사용됩니다.

다른 팁

당신이 찾고있는 대답은 "With"진술입니다.

그러나 나는 그것을 사용하지 않기 때문에 그것을 사용하지 않으며 ECMAScript 6에는 존재하지 않을 것입니다.

이런 종류의 일을 할 수 있다고 생각하는 유일한 방법은 호스트 응용 프로그램 자체 내부에서 JavaScript 환경을 외부에서 조작하는 것입니다. 또는 Rhino를 사용하는 경우 Java API와 JavaScript 사이의 링크는 Rhino의 완벽한 것이기 때문에 실제로 JavaScript 내부에서이를 수행 할 수 있습니다. Steve Yegge가 처음으로 내 마음을 날려 버렸다고 지적했을 때. JavaScript 외부에서 JavaScript 내부에서 JavaScript를 조작하십시오! 천재 야!

브라우저 환경에 갇혀 있다면 아마도 Narcissus와 같은 JavaScript로 작성된 JavaScript 통역사를 사용할 수 있습니다.

JavaScript의 내장을 사용할 수 있습니다 toString 기능 방법?

function withScope(f, scope) {
    var toExec = "";
    for (var prop in scope) {
        toExec += "var " + prop + " = scope['" + prop + "'];"
    }
    toExec += "f = (" + f.toString() + ")";
    eval(toExec);
    return f;
}
var x = 10;
var f = function() {
    console.log(x);
};
withScope(f, {x: 20})();

그래도 이것은 나쁜 생각처럼 보입니다 ...

당신은 스코프를 가지고 놀고 싶다면 당신이 즐길 수 있습니다. let JavaScript 1.7에서 제공된 진술. Firefox 지원의 최근 버전 let.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top