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

  • 所謂編譯的三個階段
    1. 分詞/詞法分析:將字符組成的字符串分解成有意義的代碼塊芳室。var a = 1;會被分解成:var,a,=,2,;.
    2. 解析/語法分析:將詞法單元流轉換成一個“抽象語法樹”(Abstract Syntax Tree闷游,AST)
    3. 代碼生成:將AST轉換為可執(zhí)行代碼
  • 作用域是根據名稱查找變量的一套規(guī)則创千。
  • “詞法作用域”就是定義在詞法階段的作用域虐唠。換句話說久锥,詞法作用域是由你在寫代碼時將變量和塊作用域寫在哪里來決定的辆床,因此當詞法分析器處理代碼時會保持作用域不變说订。
  • eval:eval()函數接受一個字符串為參數听诸,并將其中的內容視為好像在書寫時就存在于程序中這個位置的代碼坐求。
    function foo(str, a){
      eval(str);
      console.log(a,b)
    }
    var b = 2;
    foo("var b = 3;", 1)
    //也就是永遠都找不到外部的b,好像就是在動態(tài)的寫代碼一樣
    
  • 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只能在...所代表的位置中被訪問执俩,外部作用域則不行,優(yōu)點是不污染外部作用域
    • 進階----引出匿名函數(作為回調函數)癌刽,優(yōu)點顯而易見役首,不污染外部作用域
    • 立即執(zhí)行函數表達式(Immediately Invoked Function Expression,IIFE),函數被包在一對()內部妒穴,因此成了一個表達式宋税,通過在末尾加上另一對()可以立即執(zhí)行這個函數。當然函數名并不是必須的
    (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循環(huán)內部使用的變量i污染到整個函數作用域中呢蛤迎?

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

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

      • const,同樣可以用來創(chuàng)建塊作用域變量怠缸,但其值是固定的(常量)
  • 提升
    a = 2;
    var a;
    console.log(a);//輸出2
    *=================*
    console.log(a); //輸出undefined
    var a = 2;
    
    • 只有聲明會被提升,而賦值或其他運行邏輯會留在原地岔冀。函數聲明會被提升凯旭,但是函數表達式不會被提升概耻!
    foo();
    var foo = function(){
    ...
    }//錯誤使套,TypeError
    
    • 函數優(yōu)先,函數聲明和變量聲明都會被提升鞠柄,但是函數首先被提升侦高,然后才是變量,后聲明的會覆蓋掉先聲明的厌杜,比如一個函數叫foo奉呛,一個變量叫foo,那么肯定是變量會優(yōu)先夯尽。
  • 作用域閉包
  • 閉包的一次理解
function foo(){
  var a = 2;
  function bar(){
      console.log(a);
  }
  return bar;
}
var baz = foo();
baz();//2--閉包扒谱场!3孜铡咆槽!

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

  • 本質上杀饵,無論何時何地,如果將函數當做第一級的值類型并到處傳遞(就是將函數作為參數傳入另一個函數中谬擦,比如回調函數切距,定時器,事件監(jiān)聽器)惨远,你就會看到閉包在這些函數中的應用谜悟。
  • 一段神奇代碼----對閉包二次理解
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扬蕊,這又是為什么呢搀别??尾抑?

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末歇父,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子再愈,更是在濱河造成了極大的恐慌榜苫,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,378評論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件翎冲,死亡現(xiàn)場離奇詭異垂睬,居然都是意外死亡,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,970評論 3 399
  • 文/潘曉璐 我一進店門羔飞,熙熙樓的掌柜王于貴愁眉苦臉地迎上來肺樟,“玉大人,你說我怎么就攤上這事逻淌∶床” “怎么了?”我有些...
    開封第一講書人閱讀 168,983評論 0 362
  • 文/不壞的土叔 我叫張陵卡儒,是天一觀的道長田柔。 經常有香客問我,道長骨望,這世上最難降的妖魔是什么硬爆? 我笑而不...
    開封第一講書人閱讀 59,938評論 1 299
  • 正文 為了忘掉前任,我火速辦了婚禮擎鸠,結果婚禮上缀磕,老公的妹妹穿的比我還像新娘。我一直安慰自己劣光,他們只是感情好袜蚕,可當我...
    茶點故事閱讀 68,955評論 6 398
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著绢涡,像睡著了一般牲剃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上雄可,一...
    開封第一講書人閱讀 52,549評論 1 312
  • 那天凿傅,我揣著相機與錄音,去河邊找鬼数苫。 笑死聪舒,一個胖子當著我的面吹牛,可吹牛的內容都是我干的文判。 我是一名探鬼主播过椎,決...
    沈念sama閱讀 41,063評論 3 422
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼戏仓!你這毒婦竟也來了?” 一聲冷哼從身側響起亡鼠,我...
    開封第一講書人閱讀 39,991評論 0 277
  • 序言:老撾萬榮一對情侶失蹤赏殃,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后间涵,有當地人在樹林里發(fā)現(xiàn)了一具尸體仁热,經...
    沈念sama閱讀 46,522評論 1 319
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 38,604評論 3 342
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了抗蠢。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片举哟。...
    茶點故事閱讀 40,742評論 1 353
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖迅矛,靈堂內的尸體忽然破棺而出妨猩,到底是詐尸還是另有隱情,我是刑警寧澤秽褒,帶...
    沈念sama閱讀 36,413評論 5 351
  • 正文 年R本政府宣布壶硅,位于F島的核電站,受9級特大地震影響销斟,放射性物質發(fā)生泄漏庐椒。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 42,094評論 3 335
  • 文/蒙蒙 一蚂踊、第九天 我趴在偏房一處隱蔽的房頂上張望约谈。 院中可真熱鬧,春花似錦犁钟、人聲如沸窗宇。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,572評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽军俊。三九已至,卻和暖如春捧存,著一層夾襖步出監(jiān)牢的瞬間粪躬,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,671評論 1 274
  • 我被黑心中介騙來泰國打工昔穴, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留镰官,地道東北人。 一個月前我還...
    沈念sama閱讀 49,159評論 3 378
  • 正文 我出身青樓吗货,卻偏偏與公主長得像泳唠,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子宙搬,可洞房花燭夜當晚...
    茶點故事閱讀 45,747評論 2 361

推薦閱讀更多精彩內容