의 자바스크립트 예제 분석 이 글은 게리 베른하르트의 환상적인”왓”토크에 대한 경의를 표하며,그는 루비와 자바스크립트에서 일부 언어 구조의 특징을 지적한다. 당신이 이야기를 아직 보지 않은 경우,난 강력하게 당신이 시간이 걸릴 정확하게 할 것이 좋습니다! 그것은 단지 약 4 분 길고 매우 재미 있어요,약속.
그의 이야기에서,게리는 자바 스크립트 코드의 네 조각을 보여줍니다:
우리는 괄호,중괄호 및 더하기 기호를 많이 참조하십시오. 다음은 이러한 조각이 평가하는 것입니다:
+ == ""
+ {} == ""
{} + == 0
{} + {} == NaN
이 예를 처음 보았을 때,나는 생각했다:”와우,그것은 지저분 해 보인다!”결과는 일관성이 없거나 임의적 인 것처럼 보일 수 있지만 여기에 나와 함께하십시오. 이 보기의 모두는 실제적으로 아주 일관되고 처럼 보는 것처럼 나쁘다!
#단편#1: +
첫 번째 조각부터 시작하겠습니다:
+ // ""
보시다시피+
연산자를 두 개의 빈 배열에 적용하면 빈 문자열이 생성됩니다. 배열의 문자열 표현은 쉼표와 함께 연결된 모든 요소의 문자열 표현이기 때문입니다:
.toString()// "1,2,3".toString()// "1,2".toString()// "1".toString()// ""
빈 배열에는 요소가 포함되어 있지 않으므로 문자열 표현은 빈 문자열입니다. 따라서 두 개의 빈 문자열의 연결은 또 다른 빈 문자열입니다.
#단편#2: + {}
지금까지,너무 좋아. 이제 두 번째 조각을 살펴 보겠습니다:
+ {}// ""
두 개의 숫자를 다루지 않기 때문에+
연산자는 두 개의 숫자 값을 추가하는 대신 문자열 연결을 다시 수행합니다.
이전 섹션에서,우리는 이미 빈 배열의 문자열 표현이 빈 문자열 것을 보았다. 여기서 빈 개체 리터럴의 문자열 표현은 기본""
값입니다. 빈 문자열 앞에 추가하면 값이 변경되지 않으므로""
가 최종 결과입니다.
자바스크립트에서 객체는 메서드가 호출되는 객체의 사용자 지정 문자열 표현을 반환하는toString()
이라는 특수 메서드를 구현할 수 있습니다. 우리의 빈 객체 리터럴은 그러한 메소드를 구현하지 않으므로Object
프로토 타입의 기본 구현으로 되돌아갑니다.
#단편#3: {} +
나는 지금까지 그 결과가 너무 예상치 못한 것이 아니라고 주장 할 것이다. 그들은 단순히 자바 스크립트에서 유형 강제 변환 및 기본 문자열 표현의 규칙을 따르고 있습니다.
그러나{} +
은 개발자가 혼란스러워하는 곳입니다:
{} + // 0
위의 줄을 브라우저 콘솔과 같은 자바 스크립트 레플에 입력하면 왜0
(숫자 0)이 표시됩니까? 결과는 + {}
와 같은 문자열이 아니어야합니까?
수수께끼를 풀기 전에+
연산자를 사용할 수있는 세 가지 방법을 고려하십시오.:
// 1) Addition of two numeric values2 + 2 == 4// 2) String concatenation of two values"2" + "2" == "22"// 3) Conversion of a value to a number+2 == 2+"2" == 2
처음 두 경우+
연산자는 두 개의 피연산자(왼쪽 및 오른쪽)가 있기 때문에 이항 연산자입니다. 세 번째 경우+
연산자는 오른쪽에 단일 피연산자만 있기 때문에 단항 연산자입니다.
또한 자바 스크립트에서{}
의 두 가지 가능한 의미를 고려하십시오. 일반적으로{}
는 빈 객체 리터럴을 의미하지만,문 위치에 있으면 자바 스크립트 문법은{}
를 빈 블록을 의미하도록 지정합니다. 다음 코드는 개체 리터럴이 아닌 두 개의 빈 블록을 정의합니다:
{}// Empty block{ // Empty block}
의 다시 우리의 조각을 살펴 보자:
{} +
자바 스크립트 엔진이 코드를 보는 방식을 명확하게 만들기 위해 공백을 조금 변경하겠습니다:
{ // Empty block}+;
이제 우리는 여기서 무슨 일이 일어나고 있는지 명확하게 볼 수 있습니다. 우리는 빈 배열에서 작동하는 단항+
식을 포함하는 또 다른 문 뒤에 블록 문이 있습니다. 후행 세미콜론은 다음 규칙에 따라 자동으로 삽입됩니다(자동 세미콜론 삽입).
브라우저 콘솔에서+
이0
로 평가되는지 쉽게 확인할 수 있습니다. 빈 배열에는 문자열 표현으로 빈 문자열이 있으며,이 문자열은+
연산자에 의해 숫자 0 으로 변환됩니다. 마지막으로 마지막 문 값(이 경우+
)이 브라우저 콘솔에 의해 보고됩니다.
또는 두 코드 조각을 에스프리마와 같은 자바스크립트 파서에 공급하고 결과 추상 구문 트리를 비교할 수 있습니다. 여기에 대한 표준입니다 + {}
:
{ "type": "Program", "body": }, "right": { "type": "ObjectExpression", "properties": } } } ], "sourceType": "script"}
그리고 여기{} +
:
{ "type": "Program", "body": }, { "type": "ExpressionStatement", "expression": { "type": "UnaryExpression", "operator": "+", "argument": { "type": "ArrayExpression", "elements": }, "prefix": true } } ], "sourceType": "script"}
혼란은 객체 리터럴과 블록 모두에 중괄호를 사용하는 자바 스크립트 문법의 뉘앙스에서 비롯됩니다. 문 위치에서 여는 중괄호는 블록을 시작하고 식 위치에서 여는 중괄호는 개체 리터럴을 시작합니다.
#단편#4: {} + {}
마지막으로,우리의 마지막 조각을 빠르게 살펴 보겠습니다{} + {}
:
{} + {}// NaN
음,두 개의 객체 리터럴을 추가하는 것은 문자 그대로”숫자가 아닙니다”-하지만 여기에 두 개의 객체 리터럴을 추가하는 것입니까? 중괄호가 다시 당신을 속일 수 있도록하지 마십시오! 이 무슨 일이 일어나고 있는지입니다:
{ // Empty block}+{};
이전 예제와 거의 같은 거래입니다. 그러나 이제 단항 더하기 연산자를 빈 객체 리터럴에 적용하고 있습니다. 이는 기본적으로Number({})
를 수행하는 것과 동일하며,객체 리터럴을 숫자로 변환 할 수 없기 때문에NaN
이 발생합니다.
자바스크립트 엔진이 두 개의 빈 객체 리터럴로 코드를 구문 분석하려면 첫 번째 리터럴(또는 전체 코드 조각)을 괄호 안에 래핑합니다. 이제 예상 결과를 볼 수 있습니다:
({}) + {}// ""({} + {})// ""
여는 괄호를 사용하면 구문 분석기가 식을 인식하려고 시도하므로{}
를 블록(문)으로 취급하지 않습니다.
#요약
이제 네 개의 코드 조각이 이러한 방식을 평가하는 이유를 확인해야 합니다. 그것은 임의적이거나 무작위적인 것이 아닙니다;형식 강요의 규칙은 사양과 언어 문법에 규정된 대로 정확하게 적용됩니다.
여는 중괄호가 문에 나타나는 첫 번째 문자인 경우 개체 리터럴이 아닌 블록의 시작으로 해석됩니다.