JavaScript는 의도적으로 해석됩니까?


73

지나치게 까다로울 수 있으므로이 질문을하는 것은주의해야합니다. 방금 JavaScript : Definitive Guide를 열었으며 1 장의 첫 페이지에 나와 있습니다.

"자바 스크립트는 높은 수준의 동적이고 형식화되지 않은 해석 된 프로그래밍 언어입니다."

따라서 해석 된 부분이 언어 사양의 요구 사항이라고 생각합니까? 아니면 언어와 많은 구현 간의 차이점을 존중할 때 언어가 해석 된 프로그래밍 언어라고 말하는 것이 오도입니까?

자바 스크립트에 대한 정적 컴파일러는 분명히 없다 - https://stackoverflow.com/questions/1118138/is-there-a-native-machine-code-compiler-for-javascript 그래서 어쩌면이 단지 반사입니다.


AS3 / "lost"ES4와 비슷한 jscript.net이 잠시있었습니다. CIL로 바이트 코드 컴파일되었습니다.
Hey

13
V8은 명시 적으로 인터프리터가 아니라 컴파일러라고 주장 합니다.
pimvdb

@GGG JScript.Net은 여전히 ​​살아 있고 아프다. 그러나 여전히 살아 있습니다. msdn.microsoft.com/ko-kr/library/72bd815a.aspx
Jetti

1
FWIW, "형식화되지 않은"비트도 엄격하지 않습니다
Rob Agar

파이어 폭스는 FF 3.5에서 질문에 대한 답변을 한 해에 첫 번째 브라우저 기반 JIT 컴파일러를 출시 했으므로 당시에는 널리 알려지지 않았을 것입니다. 현대 JIT는 실제로 JS 문서의 첫 번째 패스에서 많은 컴파일 (또는 적어도 컴파일 준비)을 수행하여 주어진 범위로 격리 된 메소드를 식별하고 캐시하는 것과 같은 작업을 수행한다고 생각합니다.
Erik Reppen

답변:


50

따라서 해석 된 부분이 언어 사양의 요구 사항이라고 생각합니까? 아니면 언어와 많은 구현 간의 차이점을 존중할 때 언어가 해석 된 프로그래밍 언어라고 말하는 것이 오도입니까?

EcmaScript 언어 전문가는 종종 "ES 인터프리터"라는 용어를 사용하여 EcmaScript 구현을 나타냅니다. 그러나 스펙 에서는 해당 용어를 사용하지 않습니다. 특히 언어 개요 는 언어를 해석기 독립적 인 용어로 설명합니다.

ECMAScript는 객체 기반입니다. 기본 언어 및 호스트 기능은 객체에 의해 제공되며 ECMAScript 프로그램은 통신 객체의 클러스터입니다.

따라서 EcmaScript는 "호스트 환경"을 가정하며, 이는 I / O 또는 외부 세계에 대한 다른 링크를 허용하지만 인터프리터를 필요로하지 않는 모든 것을 포함하여 객체 정의 제공자로 정의됩니다.

언어의 문장과 표현의 의미 는 인터프리터에서 사소하게 구현되는 완성 사양의 관점에서 정의 되지만 사양에는 필요하지 않습니다.

8.9 완성 사양 유형

완성 유형 문장의 동작을 설명하기 위해 사용된다 ( break, continue, returnthrow) 비 로컬 제어 전송을 수행하는. 완료 유형의 값은 형식의 3 배 ( type , value , target )입니다. 여기서 typenormal , break , continue , return 또는 throw 중 하나입니다 . value 는 ECMAScript 언어 값이거나 비어 있고 target 은 ECMAScript 식별자 또는 비어 있습니다.

"급격한 완료"라는 용어 는 normal 이외 의 유형으로 완료되는 것을 말합니다 .

로컬이 아닌 제어 전송은 기본 또는 바이트 코드 컴파일을 허용하는 점프를 사용하여 명령어 배열로 변환 될 수 있습니다.

"EcmaScript Engine" 이 동일한 아이디어를 표현하는 더 좋은 방법 일 수 있습니다.


JavaScript 용 정적 컴파일러는 분명히 없습니다

사실이 아닙니다. V8 "통역사"는 내부적으로 네이티브 코드로 컴파일하고, Rhino는 선택적으로 내부적으로 Java 바이트 코드로 컴파일하며, 다양한 Mozilla 인터프리터 ({Trace, Spider, Jager} Monkey)는 JIT 컴파일러를 사용합니다.

V8 :

V8은 바이트 코드를 실행하거나 해석하는 것보다 JavaScript를 원시 머신 코드로 컴파일하여 실행하기 전에 성능을 향상시킵니다.

코뿔소 :

public final void setOptimizationLevel(int optimizationLevel)

현재 최적화 수준을 설정하십시오. 최적화 레벨은 -1과 9 사이의 정수 여야합니다. 음수 값은 -1로 해석되고 9보다 큰 값은 9로 해석됩니다. -1의 최적화 레벨은 해석 모드가 항상 익숙한. 레벨 0-9는 클래스 파일이 생성 될 수 있음을 나타냅니다. 최적화 수준이 높을수록 컴파일 시간 성능이 런타임 성능과 상쇄됩니다. 옵티 마이저 패키지가 런타임에 존재하지 않으면 옵티 마이저 레벨을 -1보다 크게 설정할 수 없습니다.

TraceMonkey :

TraceMonkey는 Mozilla의 JavaScript® 엔진 ( "SpiderMonkey")에 네이티브 코드 컴파일을 추가합니다. UC Irvine에서 개발 한 "트레이스 트리"라는 기술을 기반으로하며 Tamarin Tracing 프로젝트와 공유되는 코드와 아이디어를 기반으로합니다. 결과적으로 브라우저 크롬과 웹 페이지 컨텐츠 모두에서 속도가 크게 향상됩니다.


1
이 답변에 감사드립니다. 실제로 질문에 대답합니다. 정적 컴파일이 없다는 것에 대한 최종 의견은 실제로 어떤 구현이 코드를 컴파일하는지와 어떤 구현이 코드를 컴파일하지 않는지에 대한 소동을 일으킨다 고 가정합니다. 내가 관심을 갖는 것은 "자바 스크립트는 해석 된 언어"라는 문장의 타당성에 관한 것이다. 구현 인용과 스펙에 의한 정의 부족으로 인해 잘못된 것으로 보인다. "Definitive Guide"의 두 번째 단락을 권장하지는 않지만 그 내용을 고수 할 것입니다.
Matt Esch

@ me232,이 진술은 2008 년 이전에 실질적으로 적용되었습니다. Rhino는 이전에 주요 통역사가 아니 었으므로 무시할 당시 "최종 지침서"에 결함이있는 사람은 거의 없었습니다. 나는 책을 읽지 않았기 때문에 그 문장이 전체적인 질을 어떻게 대표하는지에 대해서는 언급 할 수 없다.
Mike Samuel

"static compiler"의 정의는 무엇입니까? 나는 정의가 컴파일이 한 번만 발생한다는 것을 의미한다고 생각하고 정적 (즉, 변경되지 않은) 비트 버킷을 얻은 다음 실행합니다. AFAIK 이것은 JavaScript 엔진의 작동 방식이 아닙니다. 그래서 그들은 de-optimization단계가 있습니다. 다시 말해 JavaScript는 이러한 엔진에 의해 컴파일되지만 정적으로 컴파일되지는 않습니다.
gman

Rhino의 바이트 코드 생성기는 @gman과 같은 방식으로 작동합니다.
Mike Samuel

AFAIK는 그렇지 않습니다. Rhino에는 런타임에 컴파일해야하는 다른 JavaScript 파일이 포함될 수 있습니다. 정적 합병증 이 아닙니다 .
gman

20

Chrome에서 사용되는 V8 JavaScript VM에는 인터프리터가 포함되어 있지 않습니다. 대신 두 개의 컴파일러로 구성되어 코드를 즉시 컴파일합니다. 컴파일러 중 하나는 빠르게 실행되지만 비효율적 인 코드를 생성하는 반면, 다른 하나는 최적화 컴파일러입니다.

V8은 코드가 실행될 때마다 사용자가 V8을 설치해야 할 때마다 소스 코드를 입력으로 사용하기 때문에 일부 사람들이 왜이 "속임수"를 고려하는지 이해할 수 있습니다. 그러나 완전한 인터프리터와 바이트 코드를 포함하는 실행 파일을 생성하는 컴파일러를 고려하십시오. 그런 다음 독립형 프로그램을 갖게됩니다. 그것은 매우 효율적이지 않을 것입니다.


19

스크립트 언어를위한 JIT 컴파일러의 출현으로 인해 컴파일과 해석 사이의 경계가 문제가 그다지 의미가없는 지점으로 바뀌 었습니다. 엔진이 한 줄의 코드를 읽고 즉시 실행할 때만 해석됩니까? (쉘 스크립트는 일반적으로 여전히 이런 방식으로 구현됩니다.) 엔진이 전체 파일을 가져 와서 즉시 일부 바이트 코드로 컴파일 한 다음 바이트 코드를 해석 할 때 해석됩니까? CPython과 마찬가지로 첫 번째 단계의 Mozilla 엔진이 이런 방식으로 작동합니다. 엔진이 한 번에 함수를 구문 분석하고이를 원시 코드로 JIT 컴파일 할 때 해석됩니까? 전체 파일을 바이트 코드로 컴파일 한 다음 필요에 따라 한 번에 하나의 함수 만 JIT하는 엔진은 어떻습니까? (요즘 대부분의 스크립트 엔진은 이런 식으로 작동합니다.

컴파일과 해석 사이에는 많은 음영이 있습니다.

해석에 가장 유용한 정의는 "별도의 사전 단계없이 실행 시간에 프로그램의 소스 코드가 제공된다"는 것입니다. 이 정의에 따르면 모든 JavaScript 엔진은 인터프리터입니다. 그러나 이것이 해석의 가능한 유일한 정의는 아닙니다.

그러나 JavaScript는 해석을 위해 설계 되었습니까? 어떤 식 으로든, 예 : 프로그램 코드를 실행할 문자열로 제공 할 수 eval있는 Function생성자 와 함수 가 있습니다. 런타임에 프로그램 코드를 동적으로 구성하려면 엔진이 소스 코드를 해석 할 수 있어야합니다. 그러나 이것이 다른 모든 것을 미리 만들 수 없다는 것을 의미하지는 않습니다. C ++ 및 C #과 같은 컴파일 된 언어에서도 소스 코드를 가져 와서 메모리에서 새 기계 코드로 컴파일 한 다음 실행할 수 있습니다. 이를위한 라이브러리도 있습니다 : C ++의 LLVM + Clang 및 C #의 Roslyn 프로젝트.

또한 JavaScript 전달 메커니즘은 소스 코드입니다. 인식 된 바이트 코드 형식이 없습니다. C #과 Java에는 공식 바이트 코드가 있으며 모든 사람들은 C ++이 기계 코드로 제공되기를 기대합니다. 그러나 이것은 언어, 단지 지배적 인 사용 시나리오라면 여전히 고유 한 측면이 아닙니다. 실제로 Flash에서 JavaScript의 밀접한 ActionScript는 바이트 코드로 제공됩니다 (Flash 컴파일러는 모든 스크립트를 사전 컴파일합니다).


4

'통역 된'과 '컴파일 된'의 정의에 완전히 동의 한 것은 없습니다. 고전적인 차이점에서 컴파일 된 언어는 독립 실행 형 이진 실행 파일을 생성하는 반면, 해석 된 언어는 코드를 실행하려면 배포 된 런타임이 필요합니다. 가상 머신, 바이트 코드 등은 구별을 흐리게합니다.

그러나 여기에는 유용한 정의가 있습니다. 해석 언어는 표준 언어 런타임이 소스 코드 텍스트를 입력으로 사용하여 실행할 수있는 언어입니다. 그 정의에 따라 Perl, Python, Ruby, JavaScript 및 쉘 스크립트 등이 해석됩니다 (바이트 코드 또는 원시 코드와 같은 중간 단계를 사용하더라도). Java, C #, C 등은 아닙니다. 스펙이 정확한 단어를 사용하지 않더라도 JavaScript는 정의에 따라 해석됩니다.


흠, Java와 C를 같은 범주에 넣는 것을 좋아하지 않습니다. 아마도 더 나은 구별은 (A) 소스 코드, (B) 중간 코드 또는 (C) 기계 코드로 가장 일반적으로 배포되는 언어입니다. 예를 들어 A = javascript, B = Java, C = C입니다.
존 헨켈

해석되거나 컴파일 된 언어를 호출하는 것은 옳지 않습니다. 예를 들어 그 규칙에 따라 C ++이 컴파일 된 언어라는 데 동의 할 것입니까? 그런 다음 Cling은 컴파일하지 않고 c ++ 코드를 실행합니다. "그리고 바이트 코드 나 심지어 네이티브 코드와 같은 중간 단계를 사용하더라도 그와 같은 것은 해석된다"이것에 따르면, 자바도 VM에 의해 해석된다.
Abhinav Gauniyal
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.