<你不知道的JavaScript(上卷)> 讀書筆記

引擎

從頭到尾負(fù)責(zé)整個(gè) JavaScript 程序的編譯及執(zhí)行過程伴箩。JavaScript 引擎不會(huì)有大量的(像其他語言編譯器那么多的)時(shí)間用來進(jìn)行優(yōu)化启涯,因?yàn)榕c其他語言不同困肩,編譯過程不是發(fā)生在構(gòu)建之前的。大部分情況下編譯發(fā)生在代碼執(zhí)行前的幾微秒的時(shí)間內(nèi)

編譯器

負(fù)責(zé)語法分析及代碼生成等臟活累活拗窃。

作用域

負(fù)責(zé)收集并維護(hù)由所有聲明的標(biāo)識(shí)符(變量)組成的一系列查詢瞎领,并實(shí)施一套非常嚴(yán)格的規(guī)則泌辫,確定當(dāng)前執(zhí)行的代碼對(duì)這些標(biāo)識(shí)符的訪問權(quán)限。作用域共有兩種主要的工作模型九默。 詞法作用域與動(dòng)態(tài)作用域

LHS 與 RHS

變量出現(xiàn)在賦值操作的左側(cè)時(shí)進(jìn)行 LHS 查詢震放,出現(xiàn)在右側(cè)時(shí)進(jìn)行 RHS 查詢

var a = 2;
  1. 遇到 var a,編譯器會(huì)詢問作用域是否已經(jīng)有一個(gè)該名稱的變量存在于同一個(gè)作用域的集合中荤西。如果是澜搅,編譯器會(huì)忽略該聲明,繼續(xù)進(jìn)行編譯;否則它會(huì)要求作用域在當(dāng)前作用域的集合中聲明一個(gè)新的變量邪锌,并命名為 a勉躺。
  2. 接下來編譯器會(huì)為引擎生成運(yùn)行時(shí)所需的代碼,這些代碼被用來處理 a = 2 這個(gè)賦值操作觅丰。引擎運(yùn)行時(shí)會(huì)首先詢問作用域饵溅,在當(dāng)前的作用域集合中是否存在一個(gè)叫作 a 的變量。如果是妇萄,引擎就會(huì)使用這個(gè)變量;如果否蜕企,引擎會(huì)繼續(xù)查找該變量
function foo(a) { // NOTE: 這里有個(gè)LHS a=2
     console.log( a ); // RHS
}
foo( 2 );

區(qū)別:

非嚴(yán)格模式下

  • RHS 查詢?cè)谒星短椎淖饔糜蛑斜閷げ坏剿璧淖兞浚婢蜁?huì)拋出 ReferenceError 異常
  • LHS 查詢時(shí)冠句,如果在頂層(全局作用域)中也無法找到目標(biāo)變量轻掩,全局作用域中就會(huì)創(chuàng)建一個(gè)具有該名稱的變量,并將其返還給引擎懦底,前提是程序運(yùn)行在非 “嚴(yán)格模式”下唇牧。 undefined
a = 2 // RIGHT
"use strict"
a = 2 // WRONG: ReferenceError

嚴(yán)格模式

  • LHS 查詢失敗時(shí),并不會(huì)創(chuàng)建并返回一個(gè)全局變量聚唐,引擎會(huì)拋出同 RHS 查詢失敗時(shí)類似的 ReferenceError 異常丐重。
  • RHS 查詢找到了一個(gè)變量,但是你嘗試對(duì)這個(gè)變量的值進(jìn)行不合理的操作杆查, 比如試圖對(duì)一個(gè)非函數(shù)類型的值進(jìn)行函數(shù)調(diào)用扮惦,或著引用 null 或 undefined 類型的值中的 屬性,那么引擎會(huì)拋出另外一種類型的異常亲桦,叫作 TypeError崖蜜。
"use strict";

false.true = "";              //TypeError
(14).sailing = "home";        //TypeError
"with".you = "far away"; 

編譯流程

  1. 分詞/詞法分析(Tokenizing/Lexing) 這個(gè)過程會(huì)將由字符組成的字符串分解成(對(duì)編程語言來說)有意義的代碼塊,
  2. 解析/語法分析(Parsing) 生成 抽象語法樹(AST)
  3. 生成代碼

提升

這意味著無論作用域中的聲明出現(xiàn)在什么地方客峭,都將在代碼本身被執(zhí)行前首先進(jìn)行處理豫领。 可以將這個(gè)過程形象地想象成所有的聲明(變量和函數(shù))都會(huì)被“移動(dòng)”到各自作用域的 最頂端,這個(gè)過程被稱為提升桃笙。
只有聲明本身會(huì)被提升,而賦值或其他運(yùn)行邏輯會(huì)留在原地沙绝。

a = 2;
var a;
console.log( a ); // 2
console.log( a ); // undefine
var a = 2; 

箭頭函數(shù)

箭頭函數(shù)在涉及 this 綁定時(shí)的行為和普通函數(shù)的行為完全不一致搏明。它放棄了所 有普通 this 綁定的規(guī)則鼠锈,取而代之的是用當(dāng)前的詞法作用域覆蓋了 this 本來的值。

閉包

function foo() {
    var a = 2;
    function bar() {
        console.log(a);
    }
    return bar;
}
var baz = foo();
baz(); // 2

以下代碼的區(qū)別

  • 盡管循環(huán)中的五個(gè)函數(shù)是在各個(gè)迭代中分別定義的星著, 但是它們都被封閉在一個(gè)共享的全局作用域中购笆,因此實(shí)際上只有一個(gè) i
for (var i = 1; i <= 5; i++) {
    setTimeout(function timer() {
        console.log(i);
    }, i * 1000);
}
  • IIFE 只是一 個(gè)什么都沒有的空作用域。它需要包含一點(diǎn)實(shí)質(zhì)內(nèi)容才能為我們所用虚循。
for (var i = 1; i <= 5; i++) {
    (function () {
        setTimeout(function timer() {
            console.log(i);
        }, i * 1000);
    })();
}
  • 在迭代內(nèi)使用 IIFE 會(huì)為每個(gè)迭代都生成一個(gè)新的作用域同欠,使得延遲函數(shù)的回調(diào)可以將新的
    作用域封閉在每個(gè)迭代內(nèi)部,每個(gè)迭代中都會(huì)含有一個(gè)具有正確值的變量供我們?cè)L問
for (var i = 1; i <= 5; i++) {
    (function (j) {
        setTimeout(function timer() {
            console.log(j);
        }, j * 1000);
    })(i); // <= 注意這里
}

模塊

  1. 為創(chuàng)建內(nèi)部作用域而調(diào)用的一個(gè)包裝函數(shù)
  2. 包裝函數(shù)的返回值必須至少包括一個(gè)對(duì)內(nèi)部函數(shù)的引用横缔,這樣就會(huì)創(chuàng)建涵蓋整個(gè)包裝函數(shù)內(nèi)部作用域的閉包铺遂。
function CoolModule() {
    var something = "cool";

    var another = [1, 2, 3];
    function doSomething() {
        console.log(something);
    }
    function doAnother() {
        console.log(another.join(" ! "));
    }
    return {
        doSomething: doSomething, doAnother: doAnother
    };
}
var foo = CoolModule(); foo.doSomething(); // cool
foo.doAnother(); // 1 ! 2 ! 3

ES6 的模塊沒有“行內(nèi)”格式,必須被定義在獨(dú)立的文件中(一個(gè)文件一個(gè)模塊)茎刚。瀏覽 器或引擎有一個(gè)默認(rèn)的“模塊加載器”(可以被重載襟锐,但這遠(yuǎn)超出了我們的討論范圍)可 以在導(dǎo)入模塊時(shí)異步地加載模塊文件。

示例代碼

var MyModules = (function Manager() {
    var modules = {};
    function define(name, deps, impl) {
        for (var i = 0; i < deps.length; i++) {
            deps[i] = modules[deps[i]];
        }
        modules[name] = impl.apply(impl, deps); // 依賴傳入
        console.log(modules[name].hello)
        /** 
         * modules 的結(jié)構(gòu)
         * {
         *    foo: { hello:  function}
         *    bar: { awesome: function}
         * }
         */
    }
    function get(name) {
        return modules[name];
    } 
    
    return {
        define: define,
        get: get
    };
})();
MyModules.define("bar", [], function () {
    function hello(who) {
        return "Let me introduce: " + who;
    }
    return {
        hello: hello
    };
});
MyModules.define("foo", ["bar"], function (bar) {
    var hungry = "hippo";
    function awesome() {
        console.log(bar.hello(hungry).toUpperCase());
    }
    return {
        awesome: awesome
    };
});
var bar = MyModules.get("bar");
var foo = MyModules.get("foo");
console.log(bar.hello("hippo")); // Let me introduce: hippo 
foo.awesome(); // LET ME INTRODUCE: HIPPO
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末膛锭,一起剝皮案震驚了整個(gè)濱河市粮坞,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌初狰,老刑警劉巖莫杈,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異奢入,居然都是意外死亡筝闹,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門俊马,熙熙樓的掌柜王于貴愁眉苦臉地迎上來丁存,“玉大人,你說我怎么就攤上這事柴我〗馇蓿” “怎么了?”我有些...
    開封第一講書人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵艘儒,是天一觀的道長(zhǎng)聋伦。 經(jīng)常有香客問我,道長(zhǎng)界睁,這世上最難降的妖魔是什么觉增? 我笑而不...
    開封第一講書人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮翻斟,結(jié)果婚禮上逾礁,老公的妹妹穿的比我還像新娘。我一直安慰自己访惜,他們只是感情好嘹履,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開白布腻扇。 她就那樣靜靜地躺著,像睡著了一般砾嫉。 火紅的嫁衣襯著肌膚如雪幼苛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評(píng)論 1 301
  • 那天焕刮,我揣著相機(jī)與錄音舶沿,去河邊找鬼。 笑死配并,一個(gè)胖子當(dāng)著我的面吹牛括荡,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播荐绝,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼一汽,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了低滩?” 一聲冷哼從身側(cè)響起召夹,我...
    開封第一講書人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎恕沫,沒想到半個(gè)月后监憎,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡婶溯,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年鲸阔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片迄委。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡褐筛,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出叙身,到底是詐尸還是另有隱情渔扎,我是刑警寧澤,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布信轿,位于F島的核電站晃痴,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏财忽。R本人自食惡果不足惜倘核,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望即彪。 院中可真熱鬧紧唱,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至遭庶,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間稠屠,已是汗流浹背峦睡。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留权埠,地道東北人榨了。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像攘蔽,于是被迫代替她去往敵國和親龙屉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354