變量聲明是全部的編程語言中最基礎部分之一。然而,JavaScript 有一個怪異點,稱之爲變量提高(hositing),這個可以讓一個看上去可有可無的聲明變成一個小bug。編程
在當前上下文遇到一個變量,若是不是私有的,則向上級上下文中查找一直找到全局上下文爲止, 若是全局上下文中也沒有:瀏覽器
二者之間存在映射關係(建立一個全局變量,也至關於給window設置一個屬性)編程語言
在全局上下文代碼執行的時候,遇到一個變量,首先看是否爲全局變量(若是是操做全局變量,【var/function聲明的會給window也設置一份】),不是全局變量則繼續看是否爲GO的屬性(若是是至關於省略window),若是也不是則按照沒有聲明這個變量的錯誤處理函數
直接輸出window.a是對象的成員訪問,哪怕沒有屬性a,屬性值是undefined,也不會報錯spa
建議從新讀一遍變量提高的概念,再作這三道題。code
console.log(a); var a=12; function fn(){ console.log(a); var a=13; } fn(); console.log(a);
console.log(a); var a=12; function fn(){ console.log(a); a=13; } fn(); console.log(a);
console.log(a); a=12; function fn(){ console.log(a); a=13; } fn(); console.log(a);
var foo='hello'; (function(foo){ console.log(foo); var foo=foo||'world'; console.log(foo); })(foo); console.log(foo);
解析:對象
代碼在執行的時候遇到大括號{}(排除函數、對象的),在看到{}中有let、const、function纔會把其當作塊級做用域。blog
if(true) { var a = 1 } // 不是塊級做用域 if(true) { let a = 1 } // 是塊級做用域 if(true) { function a(){} } // 是塊級做用域
console.log(foo) { console.log(foo) function foo() {} foo = 1; console.log(foo) } console.log(foo); // undefined function 1 function
解析:ip
建議把上面的四句話多讀幾遍再作作用域
console.log(foo); { console.log(foo); function foo() {} // 此時以前對FOO的操做不會映射,等待最後一次再處理 foo = 1; function foo() {} console.log(foo); } console.log(foo);
console.log(foo); { function foo() {} foo = 1; function foo() {} foo = 2; } console.log(foo);
公衆號地址,歡迎關注!