學習至:html
<script>
區分的代碼塊。JS是按照代碼塊 編譯 和 執行的。代碼塊間 相互獨立,可是 變量和方法 共享。前端
<script> alert('代碼塊一'); </script> <script> alert('代碼塊二'); </script>
<script> var a = 3; </script> <script> console.log(a); // 3 </script>
聲明式函數 和 賦值型函數函數
聲明函數與賦值函數的區別在於: 在 JS 的預編譯期間,聲明式函數會被先提取出來,而後才按照順序執行 JS代碼。學習
A(); // 'A ' function A() { console.log('A'); }
B(); // error, B is not a function var B = function() { console.log('B'); }
什麼是匿名函數?.net
沒有名字的函數就是匿名函數(忽然有點想笑)。code
function() {} // 匿名函數
什麼是自執行函數htm
(function() { console.log(3); })();
須要注意,下面這樣的寫法會報錯blog
function() { console.log(3); }();緣由解析以下:
function {}()
其實這是一個函數聲明。function(){}
先被預編譯了。而後JS看見了()
。JS一臉懵逼,這不得報錯嗎。還須要知道的是,自執行函數的標識能夠是
!function(){}() (function(){})() ~function(){}() void function(){}()
自執行函數是能夠帶參數的,格式是這樣的!
function(num){ console.log(num); }(3); // 3
ip
事實上,JS的解析分爲兩個階段:預編譯 和 執行期。作用域
預編譯期間:對本代碼塊
中的全部 聲明變量 和 函數進行處理(相似於 C語言的編譯) ,但須要注意,1.此時處理函數的只是 聲明式函數
2.變量也只是進行了聲明可是沒有進行初始化和賦值
編譯期間:從上到下 編譯 代碼塊。
f(); // 我是函數聲明2 function f() { console.log('我是函數聲明1'); } function f() { console.log('我是函數聲明2'); }
結論1:都是函數聲明的狀況下,後來居上的規則 沒有變。
f(); // 我是函數聲明 function f() { console.log('我是函數聲明'); } var f = function() { console.log('我是賦值型函數'); }
結論2:函數聲明 提早於 賦值函數。
console.log(a); var a; // undefined console.log(b); // 程序直接報錯,不往下進行
結論3:變量聲明 處於 預編譯階段。證實了咱們上面的正確性。
函數下方聲明瞭 a,被提早(提高)了。函數下方沒有聲明 b(以前也沒有),直接報錯。
<script> f(); // f is not defined. </script> <script> function f(){}; </script>
結論4:JS引擎是按照代碼塊的順序來執行的。!!!對於還未加載的代碼,是沒有辦法進行預處理的。這也是編譯核心所在。
console.log(f); // Function function f() { console.log(1); } var f = 3;
結論5:函數聲明提高優先級大於 變量聲明,函數聲明覆蓋 變量聲明
<script> console.log(a); </script> <script> console.log(3); </script>
結論6:代碼塊之間若是報錯,其餘的代碼塊若是正確依舊可以正確執行。
f(); var scope = 'out'; function f() { console.log(scope); // undefined var scope = 'in'; console.log(scope); // 'in' }
實際運行過程:
var scope = 'out'; function f() { var scope; // 覆蓋了外部的。 console.log(scope); scope = 'in'; console.log(scope); } f();
var getName = function(){ console.log(2); } function getName (){ console.log(1); } getName();
答案是 2. 這題看懂了前面的話很容易:
function getName (){ console.log(1); } var getName = function(){ console.log(2); } getName(); // 2
getName(); // 1 function getName() { console.log(1); } var getName = function() { console.log(2); }
依舊很容易,不解釋。變量賦值來得太慢,不像龍捲風。
JS的執行順序以下:
{ var a = 3; // 咱們覺得它只是個局域變量 } console.log(a); // 3 -- 沒想到它在全局中打印出來了,(手動笑哭)
使用了 ES6 的 let 以後, {}
內即爲一個 變量做用域。
{ let a = 3; } console.log(a); // error
變量提高 完。
complete.