你不知道的javascript(上卷)讀書筆記

  • 所謂編譯的三個階段
    1. 分詞/詞法分析:將字符組成的字符串分解成有意義的代碼塊。var a = 1;會被分解成:var,a,=,2,;.
    2. 解析/語法分析:將詞法單元流轉換成一個“抽象語法樹”(Abstract Syntax Tree,AST)
    3. 代碼生成:將AST轉換為可執行代碼
  • 作用域是根據名稱查找變量的一套規則。
  • “詞法作用域”就是定義在詞法階段的作用域。換句話說,詞法作用域是由你在寫代碼時將變量和塊作用域寫在哪里來決定的,因此當詞法分析器處理代碼時會保持作用域不變。
  • eval:eval()函數接受一個字符串為參數,并將其中的內容視為好像在書寫時就存在于程序中這個位置的代碼。
    function foo(str, a){
      eval(str);
      console.log(a,b)
    }
    var b = 2;
    foo("var b = 3;", 1)
    //也就是永遠都找不到外部的b,好像就是在動態的寫代碼一樣
    
  • with:with通常被當作重復引用同一個對象中的多個屬性的更快捷方式
    eg:var obj = {
              a:1,
              b:2
              }
       obj.a = 2;
       obj.b = 3;
    相當于:
      with(obj){
          a:2;
          b:33;
      }
    //可以方便的訪問對象屬性
    
    with可以將一個沒有或有多個屬性的對象處理為一個完全隔離的詞法作用域,因此這個對象的屬性也會被處理為定義在這個作用域中的詞法標識符。但是這個塊內部正常的var聲明并不會被限制在這個塊的作用域中,而是被添加到with所在的函數作用域中,所以就有一個新的問題,變量會被泄露。
  • 函數作用域
    • 函數作用域,函數作用域的含義是指,屬于這個函數的全部變量都可以在整個函數的范圍內使用及復用(及嵌套的作用域中也可以使用)。
    • 函數作用域的利用:在任意代碼片段外部添加包裝函數,可以將內部的變量和函數定義“隱藏”起來,外部作用域無法訪問包裝函數內部的任何內容。
    • (function foo(){...}),作為函數表達式意味著foo只能在...所代表的位置中被訪問,外部作用域則不行,優點是不污染外部作用域
    • 進階----引出匿名函數(作為回調函數),優點顯而易見,不污染外部作用域
    • 立即執行函數表達式(Immediately Invoked Function Expression,IIFE),函數被包在一對()內部,因此成了一個表達式,通過在末尾加上另一對()可以立即執行這個函數。當然函數名并不是必須的
    (function foo(){
      ...
    })()
    
    • IIFE進階用法:把它們當做函數調用并且傳遞參數進去
    var a = 2;
    (function IIFE(global){
        var a = 3;
        console.log(a);
        console.log(global.a);
    })(window);
    console.log(a);
    
    將window對象的引用傳遞進去,但將形參命名為global,因此在代碼風格上對全局對象的引用變的比引用一個沒有“全局”字樣的變量更加清晰。
    • 塊作用域,javascript是沒有塊作用域的,只要用var來聲明變量,最終都會屬于外部作用域,比如在if語句塊中聲明的變量,(函數當然是另外一回事)
    for(var i  =0; i<10; i++){
      ...
    }//i已經被泄漏到外部了
    
    • 思考:為什么要把一個只在for循環內部使用的變量i污染到整個函數作用域中呢?

      • with,是塊作用域的一個例子??!?。?!使用with從對象中創建出的作用域僅在with聲明中而非外部作用域中有效。
      • try/catch,try/catch的catch分句會創建一個塊作用域,其中聲明的變量僅在catch內部有效
      tyr{
        undefined();//執行一個非法操作來強制制造一個異常
      }
      cathc(err){
        console.log(err)//正常執行
      }
      console.log(err);//ReferenceError:err not found
      
      • let,let關鍵字可以將變量綁定到所在的任意作用域中,也就是let為其聲明的變量隱式的創建了一個塊作用域,這樣在if中用let聲明的變量就不會污染到全局作用域,那么如何顯式的創建一個塊?加大括號就行了。
      if(foo){
        {
            let bar = foo * 2;
            bar = something(bar);
            console.log(bar)
        }
      }// 這樣就顯示的創建了一個塊,只要聲明是有效的,在聲明中的任意位置都可以使用{...}來為let創建一個用于綁定的塊
      

      let進行的聲明不回在塊作用域中進行提升,也就是let聲明的變量,在let這一行運行之前是不存在的

      • const,同樣可以用來創建塊作用域變量,但其值是固定的(常量)
  • 提升
    a = 2;
    var a;
    console.log(a);//輸出2
    *=================*
    console.log(a); //輸出undefined
    var a = 2;
    
    • 只有聲明會被提升,而賦值或其他運行邏輯會留在原地。函數聲明會被提升,但是函數表達式不會被提升!
    foo();
    var foo = function(){
    ...
    }//錯誤,TypeError
    
    • 函數優先,函數聲明和變量聲明都會被提升,但是函數首先被提升,然后才是變量,后聲明的會覆蓋掉先聲明的,比如一個函數叫foo,一個變量叫foo,那么肯定是變量會優先。
  • 作用域閉包
  • 閉包的一次理解
function foo(){
  var a = 2;
  function bar(){
      console.log(a);
  }
  return bar;
}
var baz = foo();
baz();//2--閉包啊?。。?

函數bar()可以訪問foo()的內部作用域,然后將bar()函數本身當作一個值類型進行傳遞,foo()執行后,其返回值賦值給變量baz并調用baz(),實際上只是通過不同的標識符調用了內部函數bar()。神奇的地方在于bar()函數在自己定義的詞法作用域以外的地方執行了。,foo()執行之后,通常會把foo()的整個內部作用域銷毀,但是閉包可以阻止被銷毀,也就是foo()的內部作用域還在,并且由bar()本身在引用,這個引用就是閉包。

  • 本質上,無論何時何地,如果將函數當做第一級的值類型并到處傳遞(就是將函數作為參數傳入另一個函數中,比如回調函數,定時器,事件監聽器),你就會看到閉包在這些函數中的應用。
  • 一段神奇代碼----對閉包二次理解
for(var i=1; i<=5; i++){
  setTimeout(function timer(){
      console.log(i);
  }, i*1000);
}

輸出的結果是五個六,頻率為1秒,這是為什么呢???

for(var i=1; i<=5; i++){
          (function(j){
              setTimeout(function timer() {
                  console.log(j);
              },j*1000);
          })(i);
      }

輸出的結果是每秒輸出一個數字,分別是1,2,3,4,5,這又是為什么呢???

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,363評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,497評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,305評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,962評論 1 311
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,727評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,193評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,257評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,411評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,945評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,777評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,978評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,519評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,216評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,642評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,878評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,657評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,960評論 2 373

推薦閱讀更多精彩內容