懶編譯您 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 接收一個立即 編譯函數的返回值,返回值是一個懶函數,