[javascript] (1, eval) ( ‘this’) 대 eval ( ‘this’) JavaScript에서?

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간접 평가 호출이 되는 표현식 이며 간접 평가 호출은 전역 범위에서 실행되도록 보장됩니다.

내가 아직 모르는 것 :

  1. 직접 평가 호출 이 전역 범위에서 실행 되지 않는 상황은 무엇 입니까?
  2. 어떤 상황 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

편집하다

더 많은 실험을 마친 후에 thisnull또는 로 설정할 수 없다고 잠정적으로 말할 것입니다 undefined. 다른 잘못된 값 (0, ”, NaN, false)으로 설정할 수 있지만 매우 고의적으로 만 설정할 수 있습니다 .

나는 당신의 소스가 경미하고 가역적 인 두개-직장 반전으로 고통 받고 있으며 Haskell에서 일주일 동안 프로그래밍하는 것을 고려하고 싶을 것입니다.


답변

조각,

var global = (function () {
    return this || (1, eval)('this');
}());

엄격 모드에서도 전역 개체를 올바르게 평가합니다. 엄격하지 않은 모드에서의 값은 this전역 개체이지만 엄격 모드에서는입니다 undefined. 식은 (1, eval)('this')항상 전역 개체가됩니다. 그 이유는 간접적 구절에 대한 규칙을 포함합니다 eval. 에 대한 직접 호출 eval은 호출자의 범위 를 가지며 문자열 thisthis클로저 의 값으로 평가됩니다 . 간접 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 참조


답변

Q1 : 쉼표로 구분 된 여러 연속 자바 스크립트 문이 마지막 문 값을 사용합니다. 그래서:

(1, eval)함수에 대한 함수 참조 인 마지막 값을받습니다 eval(). eval()ES5의 전역 범위에서 평가 될 간접 평가 호출로 호출 을 만들기 위해 분명히 이런 방식으로 수행됩니다 . 자세한 내용은 여기에 설명되어 있습니다 .

Q2 : 글로벌을 정의하지 않는 몇 가지 환경이 있어야 this하지만, 정의 않습니다 eval('this'). 그것이 내가 그것을 생각할 수있는 유일한 이유입니다.


답변