js入門到放棄Day5(上)——作用域+預解析模塊——筆記整理+1面試經典題型+1作業..

一. 作用域

文章目錄
一. 作用域
二 . 變量的作用域
三.作用域鏈
四. 預解析

1 作用域概述

通常來說,一段程序代碼中所用到的名字並不總是有效和可用的,而限定這個名字的可用性的代碼範圍就是這個名字的作用域。作用域的使用提高了程序邏輯的局部性,增強了程序的可靠性,減少了名字衝突。

JavaScript(es6前)中的作用域有兩種:
  • 全局作用域
  • 局部作用域(函數作用域)

2 全局作用域

作用於所有代碼執行的環境(整個 script 標籤內部)或者一個獨立的 js 文件。

3. 局部作用域

作用於函數內的代碼環境,就是局部作用域。 因爲跟函數有關係,所以也稱爲函數作用域。

4 JS沒有塊級作用域

  • 塊作用域由 { } 包括。
  • 在其他編程語言中(如 java、c#等),在 if 語句、循環語句中創建的變量,僅僅只能在本 if 語句、本循環語句中使用。

Js中沒有塊級作用域(在ES6之前)

if(true){
  var num = 123;
  console.log(123); //123
}
console.log(123);   //123

二 . 變量的作用域

在JavaScript中,根據作用域的不同,變量可以分爲兩種:
  • 全局變量
  • 局部變量

2.1 全局變量

在全局作用域下聲明的變量叫做全局變量(在函數外部定義的變量)。
  • 全局變量在代碼的任何位置都可以使用
  • 在全局作用域下 var 聲明的變量 是全局變量
  • 特殊情況下,在函數內不使用 var 聲明的變量也是全局變量(不建議使用)

2.2 局部變量

在局部作用域下聲明的變量叫做局部變量(在函數內部定義的變量)
  • 局部變量只能在該函數內部使用
  • 在函數內部 var 聲明的變量是局部變量
  • 函數的形參實際上就是局部變量

2.3 全局變量和局部變量的區別

  • 全局變量:在任何一個地方都可以使用,只有在瀏覽器關閉時纔會被銷燬,因此比較佔內存
  • 局部變量:只在函數內部使用,當其所在的代碼塊被執行時,會被初始化;當代碼塊運行結束後,就會被銷燬,因此更節省內存空間

三.作用域鏈

只要是代碼都一個作用域中,寫在函數內部的局部作用域,未寫在任何函數內部即在全局作用域中;如果函數中還有函數,那麼在這個作用域中就又可以誕生一個作用域;根據在[ 內部函數可以訪問外部函數變量]的這種機制,用鏈式查找決定哪些數據能被內部函數訪問,就稱作作用域鏈

案例分析1:

function f1() {
    var num = 123;
    function f2() {
        console.log( num );
    }
    f2();
}
var num = 456;
f1();

作用域鏈:採取就近原則的方式來查找變量最終的值。

var a = 1;
function fn1() {
    var a = 2;
    var b = '22';
    fn2();
    function fn2() {
        var a = 3;
        fn3();
        function fn3() {
            var a = 4;
            console.log(a); //a的值 ?
            console.log(b); //b的值 ?
        }
    }
}
fn1();

四. 預解析

4.1 預解析的相關概念

JavaScript 解析器在運行 JavaScript 代碼的時候分爲兩步:預解析和代碼執行。

  • 預解析:在當前作用域下, JS 代碼執行之前,瀏覽器會默認把帶有 var 和 function 聲明的變量在內存中進行提前聲明或者定義。

  • 代碼執行: 從上到下執行JS語句。

    預解析會把變量和函數的聲明在代碼執行之前執行完成。

4.2 變量預解析

預解析也叫做變量、函數提升。
變量提升(變量預解析): 變量的聲明會被提升到當前作用域的最上面,變量的賦值不會提升。

console.log(num);  // 結果是多少?
var num = 10;      // ?

結果:undefined

注意:變量提升只提升聲明,不提升賦值

4.3 函數預解析

函數提升: 函數的聲明會被提升到當前作用域的最上面,但是不會調用函數。

fn();
function fn() {
    console.log('打印');
}

結果:控制檯打印字符串 — ”打印“

注意:函數聲明代表函數整體,所以函數提升後,函數名代表整個函數,但是函數並沒有被調用!

4.4 函數表達式聲明函數問題

函數表達式創建函數,會執行變量提升,此時接收函數的變量名無法正確的調用:

fn();
var  fn = function() {
    console.log('想不到吧');
}

結果:報錯提示 ”fn is not a function"

解釋:該段代碼執行之前,會做變量聲明提升,fn在提升之後的值是undefined;而fn調用是在fn被賦值爲函數體之前,此時fn的值是undefined,所以無法正確調用。


面試經典:
求輸出的值?

 f1();
        console.log(c);
        console.log(b);
        console.log(a);

        function f1() {
            var a = b = c = 9;
            console.log(a);
            console.log(b);
            console.log(c);
        }
        // 以上代碼相當於提前執行了以下代碼
        // function f1() {
        //     var a;
        //     a = b = c = 9;
        //     // 相當於 var  a  = 9; b = 9; c = 9; b 和 c 直接賦值 沒有var 聲明 當 全局變量看
        //     // 集體聲明  var a = 9, b = 9, c = 9;
        //     console.log(a);
        //     console.log(b);
        //     console.log(c);
        // }
        // f1();
        // console.log(c);
        // console.log(b);
        // console.log(a);

最終答案是:在這裏插入圖片描述


今日作業:
請描述下面代碼的輸出結果。

var num = 1;
function demo(){
    console.log(num);
    function demoSon(){
        num = 3;
    }
    var num = 2
    demoSon();
}
demo();

 //以上代碼實際先執行了以下這個代碼
        // var num;

        // function demo() {
        //     console.log(num);

        //     function demoSon() {
        //         num = 3;
        //     }
        //     var num;
        //     num = 2;
        //     demoSon();
        // }
        // demo();
        // num = 1;

答案爲undefined。


分享結束
Day5——創建對象模塊(點擊跳轉)

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章