[javascript] JavaScript에서! {} [true]가 true로 평가되는 이유는 무엇입니까?

{}[true]이다 [true]하고 ![true]있어야한다 false.

그렇다면 왜 !{}[true]평가 true합니까?



답변

일반이 때문에 나는 그의를 생각 {}[true]포함한 배열 다음에 빈 문 블록 (안 객체 리터럴)로 구문 분석 true이다 true.

한편, 도포 !조작은 파서가 해석하게 {}이하가되도록, 오브젝트 리터럴로 {}[true]복귀하는 멤버 액세스하게 undefined하고 !{}[true]true(대로 !undefined이다 true).


답변

때문에는 {}[true]반환하지 않습니다 true, 그러나 undefined, 그리고 undefined으로 평가된다 false:

http://jsfiddle.net/67GEu/

'use strict';
var b = {}[true];
alert(b); // undefined
b = !{}[true];
alert(b); // true


답변

때문에

{}[true]

로 평가 undefined되며 !undefined입니다 true.

@schlingel에서 :

true키 및 {}해시 맵으로 사용됩니다. 키가있는 속성이 true없으므로를 반환합니다 undefined. 아니 undefined되고 true, 같은 예상.

콘솔 세션 ( Node.js [0.10.17] ) :

> {}[true]
undefined
> !{}[true]
true
> [true]
[ true ]
> ![true]
false
>

그러나 Chrome 콘솔에서 :

> !{}[true]
true

따라서 불일치가 없습니다. 이전 버전의 JavaScript VM을 사용하고있을 것입니다. 추가 증거가 필요한 사람들을 위해 :

여기에 이미지 설명을 입력하십시오

최신 정보

함께 파이어 폭스 , 그것은 또한 평가 true:

여기에 이미지 설명을 입력하십시오


답변

혼란의 이유는 첫 번째 주장을 오해하기 때문입니다.

{}[true] 이다 [true]

실행할 때보고있는 것은 모호한 결과입니다. Javascript는 이와 같은 모호성을 처리하는 방법에 대해 정의 된 규칙 세트를 가지고 있으며,이 경우, 단일 명령문으로 표시되는 내용을 두 개의 개별 명령문으로 나눕니다.

따라서 Javascript는 위의 코드를 두 개의 별도 명령문으로 간주합니다. 첫째, {}가 있고 완전히 별개 [true]입니다. 두 번째 진술은 결과를 제공하는 것 [true]입니다. 첫 번째 진술 {}은 실질적으로 완전히 무시됩니다.

다음을 시도하여이를 증명할 수 있습니다.

({}[true])

즉, 인터프리터가 단일 명령문으로 읽도록 강제로 전체를 괄호로 묶습니다.

이제 문장의 실제 가치는 undefined입니다. (이것은 나중에 다음 부분을 이해하는 데 도움이 될 것입니다)

이제 우리는 귀하의 질문의 첫 부분이 빨간 청어라는 것을 알고 있으므로 질문의 마지막 부분으로 넘어 갑시다.

그렇다면 왜! {} [true]가 true로 평가됩니까?

여기에도 같은 문장이 있지만 !그 앞에 추가됩니다.

이 경우 Javascript의 규칙은 전체 내용을 단일 문으로 평가하도록 지시합니다.

앞의 문장을 괄호로 묶었을 때 일어난 일을 다시 참조하십시오. 우리는 얻었다 undefined. 이번에는 효과적으로 똑같은 일을하지만 그 일 !을 앞두고 있습니다. 그래서 코드는 다음과 같이 간단하게 할 수 !undefined있는, true.

잘만되면 그것은 조금 설명합니다.

복잡한 짐승이지만 여기서 배우는 교훈은 콘솔에서 문장을 평가할 때 괄호를 사용하여 가짜 결과를 피하는 것입니다.


답변

{}[true]입니다 undefined. 이것을 작성하려면 다음을 작성하십시오.

a = {};
a[true] === undefined // true

또는 간단히 :

({})[true] === undefined // true

우리는 알고 !undefined있다 true.


에서 @Benjamin Gruenbaum의 대답 :

Chrome dveloper 도구는 다음을 수행합니다 .

  try {
      if (injectCommandLineAPI && inspectedWindow.console) {
          inspectedWindow.console._commandLineAPI = new CommandLineAPI(this._commandLineAPIImpl, isEvalOnCallFrame ? object : null);
          expression = "with ((window && window.console && window.console._commandLineAPI) || {}) {\n" + expression + "\n}";
      }
      var result = evalFunction.call(object, expression);
      if (objectGroup === "console")
          this._lastResult = result;
      return result;
  } 
  finally {
      if (injectCommandLineAPI && inspectedWindow.console)
          delete inspectedWindow.console._commandLineAPI;
  }

따라서 기본적으로 call표현식으로 객체를 수행합니다 . 표현은 다음과 같습니다.

with ((window && window.console && window.console._commandLineAPI) || {}) {
    {}+{};// <-- This is your code
}

보시다시피, 랩핑 괄호없이 표현식이 직접 평가됩니다.

자세한 내용은 이 질문 에서 찾을 수 있습니다 .


답변

여기에 대한 답변이 좋습니다. 여기 의사 코드에 대한 분석이 있습니다.

  • {}['whatever'] = 빈 블록, NewArray ( ‘whatever’) = NewArray ( ‘whatever’)
  • {}[true] = 빈 블록, NewArray (true) = NewArray (true)
  • !{}['whatever'] = LogicalNOT (convertToBool (NewObject.whatever)) = LogicalNOT (convertToBool (undefined)) = LogicalNOT (false) = true
  • ({}['whatever']) = 그룹화 (NewObject.whatever) = 그룹화 (정의되지 않음) = 정의되지 않음

답변

이것은 {}의미에서의 리터럴 표현이 Object아니라 빈 범위 (또는 빈 코드 블록) 이기 때문에 발생합니다 .

{ var a = 1 }[true] // [true] (do the same thing)

범위 내에서 코드를 평가 한 다음 배열을 보여줍니다.

그리고 당신의

!{}[true]

이 범위를 int로 변환하고 동일한 배열을 true로 반환하십시오. 이 코드에는 부울 검사가 없습니다.

그리고 결과를 확인하려고하면 다음과 같은 결과가 나타 {}[true]납니다 false.

{}[true] -> [true] -> ![true] -> false

더 이상 범위가 없으므로.

따라서 !귀하의 질문에 다음과 같이하십시오 :

!function() {
   //...
}