JavaScript Patterns 를 읽기 시작 했는데 일부 코드가 혼란 스러웠습니다.
var global = (function () {
return this || (1, eval)('this');
}());
내 질문은 다음과 같습니다.
Q1 :
(1, eval) === eval
?
왜 그리고 어떻게 작동합니까?
Q2 : 왜 그냥
var global = (function () {
return this || eval('this');
}());
또는
var global = (function () {
return this;
}());
답변
(1,eval)
오래된 것과 평범한 차이점 eval
은 전자는 값 이고 후자는 lvalue라는 것입니다. 다른 식별자라면 더 분명 할 것입니다.
var x;
x = 1;
(1, x) = 1; // syntax error, of course!
그것은 (말 하거나 할 것 같은) (1,eval)
양보하는 표현 이지만 .eval
(true && eval)
(0 ? 0 : eval)
eval
왜 신경 쓰나요?
Ecma 사양은 참조 를 eval
“직접 평가 호출” 이라고 간주 하지만 단순히 eval
간접 평가 호출이 되는 표현식 이며 간접 평가 호출은 전역 범위에서 실행되도록 보장됩니다.
내가 아직 모르는 것 :
- 직접 평가 호출 이 전역 범위에서 실행 되지 않는 상황은 무엇 입니까?
- 어떤 상황
this
에서 전역 범위의 함수 가 전역 객체를 생성 하지 못할 수 있습니까?
여기에서 더 많은 정보를 얻을 수 있습니다 .
편집하다
내 첫 번째 질문에 대한 대답은 “거의 항상”입니다. 현재 범위 eval
에서 직접 실행됩니다 . 다음 코드를 고려하십시오.
var x = 'outer';
(function() {
var x = 'inner';
eval('console.log("direct call: " + x)');
(1,eval)('console.log("indirect call: " + x)');
})();
당연히 (heh-heh) 다음과 같이 출력됩니다.
direct call: inner
indirect call: outer
편집하다
더 많은 실험을 마친 후에 this
는 null
또는 로 설정할 수 없다고 잠정적으로 말할 것입니다 undefined
. 다른 잘못된 값 (0, ”, NaN, false)으로 설정할 수 있지만 매우 고의적으로 만 설정할 수 있습니다 .
나는 당신의 소스가 경미하고 가역적 인 두개-직장 반전으로 고통 받고 있으며 Haskell에서 일주일 동안 프로그래밍하는 것을 고려하고 싶을 것입니다.
답변
조각,
var global = (function () {
return this || (1, eval)('this');
}());
엄격 모드에서도 전역 개체를 올바르게 평가합니다. 엄격하지 않은 모드에서의 값은 this
전역 개체이지만 엄격 모드에서는입니다 undefined
. 식은 (1, eval)('this')
항상 전역 개체가됩니다. 그 이유는 간접적 구절에 대한 규칙을 포함합니다 eval
. 에 대한 직접 호출 eval
은 호출자의 범위 를 가지며 문자열 this
은 this
클로저 의 값으로 평가됩니다 . 간접 eval
은 전역 범위의 함수 내에서 실행 된 것처럼 전역 범위에서 평가됩니다. 이 함수는 그 자체가 엄격 모드 함수가 아니기 때문에 전역 객체는 as로 전달되고 this
표현식 'this'
은 전역 객체로 평가됩니다. 이 표현 (1, eval)
은eval
간접적이어서 전역 객체를 반환합니다.
A1은 : (1, eval)('this')
동일하지 않습니다 eval('this')
때문에 간접 구절 직접 호출 주위에 특별한 규칙 eval
.
A2 : 원본은 엄격 모드에서 작동하지만 수정 된 버전은 작동하지 않습니다.
답변
Q1 :
나는 이것이 JS에서 쉼표 연산자의 좋은 예라고 생각합니다. 이 기사에서 쉼표 연산자에 대한 설명이 마음에 듭니다 . http://javascriptweblog.wordpress.com/2011/04/04/the-javascript-comma-operator/
쉼표 연산자는 두 피연산자 (왼쪽에서 오른쪽으로)를 모두 평가하고 두 번째 피연산자의 값을 반환합니다.
Q2 :
(1, eval)('this')
간접 평가 호출로 간주되며 ES5에서는 전역 적으로 코드를 실행합니다. 따라서 결과는 글로벌 컨텍스트가 될 것입니다.
http://perfectionkills.com/global-eval-what-are-the-options/#evaling_in_global_scope 참조