1. 程式人生 > 實用技巧 >函式、箭頭函式、函式作用域、塊級作用域、作用域鏈

函式、箭頭函式、函式作用域、塊級作用域、作用域鏈

函式

範例

    function sum(a,b) {
        let result = a + b;
        return result;
    }

    let a = sum(1,5) //a = 6

吃的是草,擠的是奶
當一段程式碼需要多次執行時,考慮封裝為函式
先宣告,再呼叫;呼叫才真正執行

兩種宣告方式

函式宣告

    function sum(a,b) {
        let result = a + b;
        return result;
    }
    
    sum(1,4)

函式表示式

    const sum = function(a,b){
        let result = a + b ;
        return result;
    }

    sum(1,6) //7

引數

宣告時可以設定形參

        const sum = function (a, b) { //a,b在這裡寫在function裡面,稱為形參
            let result = a + b;
            return result;
        }
        let a = sum(1, 5) //呼叫之後,a=1,b=5,成為實參

arguments

arguments是一個物件,它儲存的是你呼叫的時候存的實參

    const sum = function(a,b){
        console.log(arguments); // 檢視控制檯
        let result = a + b ;
        return result;
    }

    sum(1,6) //7

arguments[0] === a
arguments[1] === b

那麼arguments有什麼用呢?試想,剛剛我們寫的function sum(a,b),這個函式只能傳遞兩個引數,如果我要計算1+3+5+9呢?或者我就要輸入更多1+6+8+4+5+···+10呢?這樣的話我們不可能寫成function sum(a,b,c,d,e,f,g,···,z)怎麼多個引數吧??所以我們可以利用arguments,因為arguments儲存的就是輸入的形參,然後我們遍歷arguments就好了

            const sum = function () {
                let result = 0;
                for (i = 0; i < arguments.length; i++) {
                    result += arguments[i]
                }
                return result;
            }

            console.log(sum(1));//1
            console.log(sum(1,2,3));//6
            console.log(sum(1,2,3,4,5));//15
            console.log(sum(1,0,1,2));//4

返回值

使用return把結果匯出

function sum(a, b){
return a + b
}
console.log( sum(2, 4) )

函式執行到return就立即終止
如果沒設定return,預設返回的是undefined

為什麼下面這個例子返回的result是這樣子的?

        const sum = function (a, b) {
            let result = a + b;
            return console.log(result); // 3
        }
        let test1 = sum(1, 2);
        console.log(test1); // undefined

因為sum函式返回的是一個函式(console.log())

箭頭函式

箭頭函式簡化函式表示式

const fn = name => "hello" + name;

等價於

const fn = function(name){
    return "hello" + name;
}

    let arr = [1, 3, 5, 6];

    const sumOfSquares = function (arr) {
        let result = 0;
        for (let val of arr) {
            result += val ** 2;
        }
        return result;
    }

    //等價於

    const sumOfSquares = arr => {
        let result = 0;
        for (let val of arr) {
            result += val ** 2;
        }
        return result;
    }

    console.log(sumOfSquares(arr));//71

函式命名

  • 動詞、動賓
    • sum、hide、show
    • printName、sayHello
  • 返回一個非布林值
    • getData、getBooks
  • 設定內容
    • setInfo、setData
  • 返回一個布林值
    • canClicked、hasMoney、isEnabled

宣告前置

var 宣告前置(變數提升 hoisting)

看看下面為什麼列印結果會這樣

console.log(a);//undefined
var a = 1 ;
console.log(a);//1

為什麼呢?
其實JavaScript在執行的時候,會有一個變數提升,執行程式碼的時候會先掃描一遍程式碼,變數提升之後才會從上往下執行程式碼。上面的例子其實是這樣的:

//start 掃描:
var a;
console.log(a);//因為var a 沒有賦值,所以打印出來的a是undefined
a = 1;
console.log(a);//1
function doSomething(){
   console.log(b);
   var b = 100;
   console.log(b);
}



doSomething();//undefined 、 100

// 等價於

function doSomething(){
   var b ;
   console.log(b);
   b = 100;
   console.log(b);
}

注意:let宣告的函式,必須要初始化之後才可以使用。

function fn(){
  console.log(cc); //Error 報錯
  let cc = 19;
  console.log(cc);
}

function 宣告前置

fn()
function fn(){
  console.log("hello world");
}

// 預掃描的時候

function fn(){   //function 宣告前置
  console.log("hello world");
}

fn()

注意:

fn2() //會報錯,函式表示式不會前置
const fn2 = function() { console.log('fn2') }

執行環境(函式作用域)

        console.log('in 全域性 start');
        foo();
        console.log('in 全域性 end');
        function foo() {
            console.log('in foo')
            bar()
            function bar() {
                console.log('in bar')
            }
        }

作用域鏈

函式在執行的過程中,先從自己內部找變數

如果找不到,再從建立當前函式所在的作用域(詞法作用域)去找, 以此往上,直到全域性作用域

注意找的是變數的此刻的狀態