Programming

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

procodes 2020. 6. 29. 21:20
반응형

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] is undefined. To find that write this:

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

or simply:

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

We know that !undefined is true.


From @Benjamin Gruenbaum's answer:

Chrome dveloper tools does the following:

  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;
  }

So basically, it performs a call on the object with the expression. The expression being:

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

So, as you can see, the expression is being evaluted directly, without the wrapping parenthesis.

More information can be found in this question.


The answers here are good, here's a breakdown in pseudo-code:

  • {}['whatever'] = empty block, NewArray('whatever') = NewArray('whatever')
  • {}[true] = empty block, NewArray(true) = NewArray(true)
  • !{}['whatever'] = LogicalNOT(convertToBool(NewObject.whatever)) = LogicalNOT(convertToBool(undefined)) = LogicalNOT(false) = true
  • ({}['whatever']) = Grouping(NewObject.whatever) = Grouping(undefined) = undefined

This happens because {} in your meaning is not literal presentation of Object, but empty scope ( or empty code block ):

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

It just evaluates code inside scope and then shows you your array.

And from your

!{}[true]

Just converts to int this scope and return same array true. There is no bool checks in this code.

And if you will try to check result from {}[true] you will get your false:

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

As there is no more any scope.

So ! in your question do the same as:

!function() {
   //...
}

  • {} is an object with no properties.
  • Since [] immediately follows an object, it means "Access a property of this name" and not "Create an array"
  • true is a boolean, but is being used as an property name so it is cast to a string ("true")
  • The object does not have a property called true (since it has no properties) so {}['true'] is undefined
  • !undefined casts undefined to a boolean (false)
  • The not operator turns false into true.

You're not reversing the value of it.

![true] != [!true]

Check this out: Why is !true ? 'false' : 'true' returning 'true'?


Let's Play a Little More!

First, let's have some fun!:

//----------#01#-----------
{}[true]; //[true]

//----------#02#-----------
var a = {}[true]; 
      console.log(a); //undefined

//----------#03#-----------
{ b: 12345 }[true]; //[true]

//----------#04#-----------
{ b: 12345 }["b"]; //evaluates to ["b"] ?!?

//----------#05#-----------
{ b: 12345 }.b; // "Unexpected token ."

//----------#06#-----------
({ b: 12345 }).b; //12345

//----------#07#-----------
var c = { b: 12345 }.b; 
      console.log(c); //12345

//----------#08#-----------
var c = { b: 12345 }["b"];
      console.log(c); //12345

//----------#09#-----------
{ true: 54321 }[true]; // "SyntaxError: Unexpected token : "

//----------#10#-----------
var d = { true: 54321 }[true]; //No error here ¬¬
      console.log(d); //54321

//----------#11#-----------
!{}[true]; // true

Ok, let's try to understand these crazy behaviors, one by one:

1) Here, the {} is parsed as an empty code block. Without an assign, negation, grouping (with parentheses) or any syntax which indicates to the parser that this {} is an object literal, the default assumption is to think it is simply a useless empty block.

This is a proof of this behavior:

{ alert(123) }[true]

The code above will show the alert normally, and will be evaluated as [true], in the same way {}[true] is.

Block Statements Without Semicolons

A block-type statement doesn't need a semicolon after it.

For instance:

for(var i=0; i < 1; i++){}function a(){};alert("Passed here!");if(true){}alert("Passed here too!")

Both alerts are shown.

So, we can see that an empty block statement, without a semicolon, is valid and simply does nothing. This way, when you enter {}[true] in the Developer Tools (or Firebug) Console, the evaluated value will be the value of the last expression statement. In this case, the last expression statement is [true].

2) In an assignment context, the parser will make sure that {} is an object literal. When you do var a = {}[true], you remove any ambiguity and tip the parser off that {} is not a block statement.
So, here, you're trying to get a value with a key "true" from an empty object. Obviously, there's no key-value pair with this key name. This way, the a variable is undefined.

Reserved words as Object keys

ECMAScript 5 allows object keys to be reserved words. So, the following keys are legal:

var obj = {if: 111, for: 222, switch: 333, function: 444, true: 555}

3) The same explanation of example 1. But... If the { b: 12345 } part is treated as a block statement, what's the type of the b: 12345 statement??

... (?????)

It's a label statement, you already saw it before... It's used in loops and in switch. Here are a few interesting links about label statements: 1, (2)[Best way to break from nested loops in Javascript?, (3)[How to break nested loops in javascript?.

NOTE: Just try to evaluate this:

{a: 1, b: 2} //=>>>SyntaxError: Unexpected token :

Label statements can't be separeted by the comma operator, you would need to separate them with a semicolon. So this is valid: {a: 1; b: 2}

4) See the explanations for the examples 1 and 3...

5) One more time, we have a { b: 12345 } being treated as a code block, and you're trying to access a property of a code block by using the dot notation, and obviously, this is not allowed, and the parser throws an "Unexpected token :" exception.

6) The code is almost identical to the above example, but by surrounding the { b: 12345 } statement with the expression grouping operator, the parser will know that is an object. This way, you'll be able to access the "b" property normally.

7) Remember the example 2, we have an assignment here, the parser knows that { b: 12345 } is an object.

8) Identical to the above example, but instead of the dot notation, here we're using the bracket notation.

9) I already said that this "identifier: value" syntax inside a block statement is a label. But, you also have to know that a label name can't be a reserved keyword (the opposite of object property names). When we tried to define a label called "true", we got a SyntaxError.

10) Again, we're dealing with an object. No problems using reserved words here. =)

11) Finally, we have this: !{}[true]

Let's separate the things here:

a) By doing a negation, we're informing to the parser that the {} is an object.

예에 도시 된 바와 같이, b) 2 하는 {}객체라는 속성이없는 true이런 식으로 계산한다 그래서 undefined.

c) 최종 결과는 undefined가치 의 부정이다 . Javascript는 암시 적 유형 변환을 수행 하며 undefined값이 잘못되었습니다 .

d) 따라서 부정 false은 ... true!

참고 URL : https://stackoverflow.com/questions/19702805/why-does-true-evaluate-to-true-in-javascript

반응형