이 글의 제목을 보면 이 글을 쓰거나 읽는 분들이 바보는 아닌 것 같습니다. 그러나 때로는 어떤 주제가 당신을 바보처럼 느끼게 만들며, 적어도 나에게는 JavaScript 엔진이 그러한 주제 중 하나입니다.
때때로 웹 애플리케이션용 코드를 작성하는 것이 마술처럼 느껴질 때가 있습니다. 일련의 문자를 작성하고 브라우저에서 그 효과를 확인하기 때문입니다. 하지만 마법 뒤에 숨은 기술을 이해하면 프로그래밍 기술을 더 잘 향상하는 데 도움이 될 수 있습니다. 적어도 JavaScript 기반 웹이나 모바일 앱의 뒤에서 무슨 일이 일어나고 있는지 설명하려고 할 때 바보처럼 느껴지지는 않을 것입니다.
수년 전, 제가 대학원 강사였을 때, 저는 학부생들에게 가르칠 수 있는 특히 어려운 프랑스어 문법을 아직 마스터하지 못했다고 교수님에게 불평했습니다. 당시 그녀가 했던 말이 기억납니다. "때때로 무언가를 배우는 유일한 방법은 가르치는 것입니다.
엔지니어에게 JavaScript 엔진을 통해 NativeScript가 런타임에 네이티브 API를 연결하고 호출하는 방식으로 백그라운드에서 작동하는 방식을 설명하십시오. 이렇게 복잡한 작업에 직면하면 잡초 속에서 길을 잃기 쉽습니다. 사실 모든 JavaScript 개발자는 우리가 매일 사용하는 기술의 기반이 되는 엔진에 대해 궁금해해야 합니다. 이제 JavaScript 엔진이 실제로 무엇을 하는지, 왜 플랫폼마다 다른 엔진을 사용하는지, 수년에 걸쳐 어떻게 발전해왔는지, 개발자로서 우리가 관심을 가져야 하는 이유를 자세히 살펴보겠습니다.
먼저 전문용어
'자바스크립트 엔진'은 종종 가상 머신이라고도 합니다. "가상 머신"은 특정 컴퓨터 시스템의 소프트웨어 기반 에뮬레이터를 의미합니다. 가상 머신에는 다양한 유형이 있으며 실제 물리적 머신을 얼마나 정확하게 시뮬레이션하거나 대체하는지에 따라 분류됩니다.
예를 들어 "시스템 가상 머신"은 운영 체제를 실행할 수 있는 완전한 에뮬레이션 플랫폼을 제공합니다. Mac 사용자에게 친숙한 Parallels는 Mac에서 Windows 시스템을 실행할 수 있게 해주는 가상 머신입니다.
반면 "프로세스 가상머신"은 모든 기능을 갖고 있지 않고 프로그램이나 프로세스를 실행할 수 있습니다. Wine은 Linux 시스템에서 Windows 애플리케이션을 실행할 수 있게 해주는 프로세스 가상 시스템이지만 Linux에서 완전한 Windows 운영 체제를 제공하지는 않습니다.
자바스크립트 가상 머신은 자바스크립트 코드를 해석하고 실행하도록 특별히 설계된 프로세스 가상 머신입니다.
참고: 브라우저에서 페이지 레이아웃을 배치하는 레이아웃 엔진과 코드를 해석하고 실행하는 기본 JavaScript 엔진을 구별하는 것이 중요합니다. 여기에서 좋은 설명을 찾을 수 있습니다.
그럼, 자바스크립트 엔진이란 정확히 무엇이고 어떤 역할을 할까요?
JavaScript 엔진의 기본 작업은 개발자가 작성한 JavaScript 코드를 브라우저에서 해석하거나 애플리케이션에 내장할 수 있는 효율적이고 최적화된 코드로 변환하는 것입니다. 실제로 JavaScriptCore는 스스로를 "최적화된 가상 머신"이라고 부릅니다.
더 정확하게 말하면 각 JavaScript 엔진은 JavaScript가 포크인 ECMAScript 버전을 구현합니다. ECMAScript가 계속 발전함에 따라 JavaScript 엔진도 계속해서 개선되고 있습니다. 이렇게 다양한 엔진이 있는 이유는 각 엔진이 서로 다른 웹 브라우저, 헤드리스 브라우저 또는 Node.js와 같은 런타임 환경에서 실행되도록 설계되었기 때문입니다.
웹 브라우저에 익숙하시겠지만, 헤드리스 브라우저란 무엇인가요? 그래픽 사용자 인터페이스가 없는 웹 브라우저입니다. 웹 제품 테스트를 자동화할 때 유용합니다. 좋은 예가 PhantomJS입니다. 그렇다면 Node.js는 JavaScript 엔진과 어떤 관련이 있습니까? Node.js는 서버 측에서 JavaScript를 사용할 수 있게 해주는 비동기식 이벤트 중심 프레임워크입니다. JavaScript를 구동하는 도구이므로 JavaScript 엔진으로도 구동됩니다.
위의 가상 머신 정의에 따르면 자바스크립트 엔진의 유일한 목적은 자바스크립트 코드를 읽고 컴파일하는 것이므로 프로세스 가상 머신이라고 부르는 것이 이해하기 쉽습니다. 그렇다고 해서 단순한 엔진이라는 뜻은 아닙니다. 예를 들어 JavaScriptCore에는 JavaScript 코드를 분석, 해석, 최적화 및 가비지 수집할 수 있는 6개의 "빌딩 블록"이 있습니다.
어떻게 작동하나요?
물론 엔진에 따라 다릅니다. 우리의 관심을 끌었던 두 가지 주요 엔진은 WebKit의 JavaScriptCore와 Google의 V8 엔진으로, 둘 다 NativeScript를 활용합니다. 두 엔진은 서로 다른 방식으로 코드를 처리합니다.
JavaScriptCore는 스크립트를 해석하고 최적화하기 위해 일련의 단계를 수행합니다.
소스 코드를 명확한 의미를 지닌 일련의 기호나 문자열로 분해하는 어휘 분석을 수행합니다.
그런 다음 구문 분석기를 사용하여 이러한 기호를 분석하여 구문 트리를 만듭니다.
그런 다음 4개의 JIT(Just-In-Time) 프로세스가 참여하기 시작하여 파서에서 생성된 바이트코드를 분석하고 실행합니다.
무엇? 간단히 말해서, JavaScript 엔진은 소스 코드를 로드하고 이를 문자열로 나누고(토큰화라고도 함) 이러한 문자열을 컴파일러가 이해할 수 있는 바이트코드로 변환한 다음 이러한 바이트코드를 실행합니다.
Google의 V8 엔진은 C로 작성되었으며 JavaScript 소스 코드를 컴파일 및 실행하고 메모리 할당 및 가비지 수집을 처리할 수도 있습니다. 소스 코드를 기계어 코드로 직접 컴파일할 수 있는 두 개의 컴파일러로 구성되도록 설계되었습니다.
풀 코드젠: 최적화되지 않은 코드를 출력하는 빠른 컴파일러
크랭크샤프트: 효율적이고 최적화된 코드를 출력하는 느린 컴파일러
Crankshaft가 최적화가 필요한 코드가 Full-codegen에 의해 생성된 최적화되지 않은 코드라고 판단하면 "crankshafting"이라는 프로세스인 Full-codegen을 대체합니다.
컴파일 프로세스 중에 기계어 코드가 생성되면 엔진은 ECMA 표준에 지정된 모든 데이터 유형, 연산자, 객체, 함수 또는 런타임에 사용해야 하는 모든 것을 브라우저에 노출합니다. 네이티브스크립트.
어떤 JavaScript 엔진이 있나요?
클라이언트측 코드를 해석, 분석 및 실행하는 데 사용할 수 있는 다양한 JavaScript 엔진이 있습니다. 각 브라우저 버전이 출시되면 JavaScript 코드 실행 기술의 변화를 따라잡기 위해 JavaScript 엔진이 변경되거나 최적화될 수 있습니다.
이러한 브라우저 엔진의 이름을 완전히 혼동하기 전에 이러한 엔진과 이를 기반으로 하는 브라우저에 많은 마케팅이 적용된다는 점을 기억하세요. JavaScript 컴파일에 대한 이 매우 유용한 분석에서 저자는 다음과 같이 냉소적으로 지적합니다. "당신이 모르는 것은 컴파일러가 약 37%의 마케팅이라는 것입니다. 그리고 컴파일러의 브랜드를 바꾸는 것은 당신이 할 수 있는 몇 안 되는 일 중 하나입니다. , 스마트 마케팅, 따라서 이름: SquirrelFish, Nitro, SFX..."
이러한 엔진의 이름 지정 및 이름 변경에 대한 마케팅의 영향을 염두에 두면서 JavaScript 엔진의 역사에서 몇 가지 중요한 사건을 언급하는 것이 유용합니다. 여러분을 위해 이해하기 쉬운 차트를 만들었습니다.
브라우저, 헤드리스 브라우저 또는 런타임 | 자바스크립트 엔진 |
---|---|
모질라 | 스파이더몽키 |
크롬 | V8 |
사파리 | 자바스크립트 코어 |
IE와 엣지 | 차크라 |
팬텀JS | 자바스크립트 코어 |
HTML단위 | 코뿔소 |
TripleJS | V8 |
Node.js | V8 |
Io.js* | V8 |
*JavaScriptCore は SquirrelFish として書き直され、アップグレードされたバージョンは QuirrelFish Extreme (Nitro とも呼ばれます) です。ただし、Webkit 実装の基礎となる JavaScript エンジンは JavaScriptCore (Safari と同様) です。
**iOS 開発者は、モバイル デバイスの Safari が Nitro を使用していることを知っておく必要がありますが、UIWebView には JIT コンパイルが含まれていないため、エクスペリエンスが遅くなります。ただし、開発者は iOS 8 で Nitro を含む WKWebView を使用できるようになり、エクスペリエンスが大幅に高速化されます。ハイブリッド モバイル アプリの開発者は、安堵のため息をつくことができるはずです。
*io.js が最終的に Node.js から分離された理由の 1 つは、V8 バージョンのエンジンをサポートするためでした。ここで述べられているように、これは依然として課題です。
なぜ注意を払う必要があるのでしょうか?
JavaScript エンジンのコード解析および実行プロセスの目標は、最も最適化されたコードを最短時間でコンパイルすることです。
最も重要なことは、これらのエンジンの進化は、可能な限りパフォーマンスを向上させるために進化する Web およびモバイル プラットフォームの継続的な探求と密接に関係しているということです。この進化を追跡するには、arewefastyet.com がまとめたベンチマーク グラフでさまざまなエンジンのパフォーマンスを確認できます。たとえば、Chrome のパフォーマンスを V8 エンジンと非クランクシャフト エンジンで比較してみると興味深いでしょう。
Web 開発者は、私たちが一生懸命書いてデバッグし、保守しているコードは、ブラウザーが異なれば必然的にパフォーマンスも異なることを認識する必要があります。特定のコードが、あるブラウザでは動作が遅いのに、別のブラウザでははるかに高速に動作するのはなぜですか?
同様に、モバイル開発者、特に Web ビューを使用してページ コンテンツを表示するハイブリッド モバイル アプリ開発者や、NativeScript などのランタイム環境を使用する開発者は、どのエンジンが JavaScript コードを解釈して実行しているかを知りたいと考えています。モバイル Web 開発者は、小型デバイス上のブラウザーの制限と可能性を認識する必要があります。成長を続けたい Web、モバイル、またはアプリケーションの開発者として、JavaScript エンジンの変化に常に注意を払うことは、大きな成果をもたらします。
概要:
JS の基本データ型未定義の null ブール数値文字列
object は js の複合データ型であり、すべてのオブジェクトの基本型です
。
js には、他の言語と同様に 9 つの基本的な制御ステートメントがあります
js の関数は戻り値を指定する必要はありません。実際、戻り値を指定しない関数は unknown
を返します。
js 内のパラメータは自由に渡すことができます。arguments[] 配列に注目してください。
js 内の関数はオーバーロードできませんが、模倣することはできます。