有關您的 javascript 函式編譯(上)
懶編譯您 javascript
marja 的 parsing javascript better lazy than eager
解析什麼是解析
-
解析javascript code 為 AST 和 Scope 作用域
今天我們之關心這部分內容 - 生成位元組碼, 這個位元組碼用於直譯器
- 優化編譯為機器碼在電腦上執行
我們通常認為 javascript 是一門解釋性還是編譯的語言呢
sum(1,2) function sum(a,b){ return a + b; }
function foo(){ let a = 0; if(a == 0){ let b = "bar"; return a; } }
從上面程式碼執行沒有問題來看 javascript 應該屬於編譯語言。
準備用 mac 的 keynote 畫樹形結構圖,感覺連線有點費勁放棄了。
- 第一層是 foo函式對應節點 FunctionIterial
let a = 0;
- 當我們宣告建立一個變數同時就生成一個變數的代理。 然後就是我們的賦值語句。分別是變數代理和
if(a == 0){ let b = "bar"; return a; }
-
看一下我們的條件語句
因為沒有 else 只有 if 所以就走 then。
作用域分析
# 為什麼我們需要關注解析
因為我們parsing
不同的瀏覽器對lazy 定義也不同,由於 javascript 本身並沒有 spec 來定義lazy 。
#### V8 有兩種有兩種解析 模式
- eager parser進行完全的解析, 構建 AST、 構建作用域, 檢查語法錯誤。
- lazy preParser 構建 scope(作用域)而不構建 AST,
lazy 和 eager
let a = 0; //IIFE (immediately invoked function express) (function() eager() { // stuff })(); function lazy(){ //stuff } lazy();
- 通過()()包裹函式是立即執行函式
- 即使 lazy 在最頂層被定義,lazy 也是懶函式,只有在呼叫才會執行。
!function eager2(){ // stuff },function eager3(){ // stuff }
在函式前面新增 !表示這個函式是立即執行函式, 後面通過逗號間隔的也同樣是立即執行函式。
也有一些特殊的情況
let f1 = function lazy() { // stuff } let f2 = function lazy(){ // stuff }()
f1 變數接受 lazy函式作為值,作為懶函式來處理
f2接受這個函式執行的結果作為 f2,首先我們看 lazy 應該是懶函式,但是他被立即執行了。
那麼懶函式跟我們有關係嗎?
因為不是所有載入 javascript都會被執行的,所以我們需要賴載入來提高效率。
- 如果一個 eager 立即編譯函式沒有被呼叫, 這就是一種浪費。
- 如果一個懶函式被執行了,當然也是一種資源的浪費,因為我們將這個函式編譯了兩次,第一次編譯可能需要 0.5 ,第二次又進行了編譯,所以一共 1.5 時間。
強制函式為立即編譯模式
(function a(){})
Optimize.js 將那些將會在引用中(上面的情況) 進行包裹讓他變成立即編譯函式
ctxt分配,賴函式我們需要分配 ctxt
let f = (function outer(){ let a = 20; function inner(){ return 1 } return inner; })(); console.log(f());
我們看一看上面的程式碼的 f 接收一個立即編譯函式的返回值,返回值是一個懶函式,