js學(xué)習(xí)筆記4(函數(shù))

1.箭頭函數(shù)

ES6新增屬性。箭頭函數(shù)特別適合嵌入函數(shù)的場(chǎng)景。

    //只有一個(gè)參數(shù),括號(hào)可以省略
    let double = x => {return 2 * x};
    let tripble = (x) => {return 2 * x};

    //沒(méi)有參數(shù)需要括號(hào)
    let getRandom = () => {return Math.random();};

    //有多個(gè)參數(shù)需要括號(hào)
    let sum = (a, b) => {return a + b}
    /**
     * 箭頭函數(shù)也可以不使用大括號(hào),但這會(huì)改變函數(shù)的行為。如果不使用大括號(hào)
     * 那么箭頭后面就只能有一行代碼(賦值操作或者表達(dá)式),而且省略大括號(hào)
     * 會(huì)隱式返回這行代碼的值。
     */
    let fun1 = (x) => {return 2 * x;}
    let fun2 = (x) => 2 * x; //等于上面的寫(xiě)法
    let fun3 =  (x) => return  2 * x ; //無(wú)效寫(xiě)法

箭頭函數(shù)雖然語(yǔ)法簡(jiǎn)介,但是很多場(chǎng)合不適用。箭頭函數(shù)不能使用arguments、super、new.target,也不能用作構(gòu)造函數(shù)。箭頭函數(shù)也沒(méi)有protptype屬性。

2.函數(shù)名

因?yàn)楹瘮?shù)名就是指向函數(shù)的指針,所以它們跟其他包含對(duì)象指針的變量具有相同的行為。
在ES6中,所有的函數(shù)對(duì)象都會(huì)暴露一個(gè)只讀的name屬性,其中包含關(guān)于函數(shù)的信息。

    function sum(num1, num2) { return num1 + num2; }
    console.log(sum(1,2)); //3
    let anotherSum = sum;
    sum = null;
    console.log(anotherSum(1,2)); //3
    console.log(anotherSum.name) //sum 返回的是方法名
    anotherSum.name = '小馬哥';
    console.log(anotherSum.name) //sum  name屬性只讀,不能修改
3.理解參數(shù)

ECMAScript函數(shù)即不關(guān)心傳入的參數(shù)個(gè)數(shù),也不關(guān)心這些參數(shù)的數(shù)據(jù)類(lèi)型。定義函數(shù)時(shí)要接收2個(gè)參數(shù),并不意味著調(diào)用的時(shí)候就要傳入2個(gè)參數(shù),可以傳1個(gè),3個(gè)甚至一個(gè)都不傳。事實(shí)上,在使用function關(guān)鍵字定義(非箭頭)函數(shù)時(shí),可以在函數(shù)的內(nèi)部訪問(wèn)arguments對(duì)象,從中獲取傳進(jìn)來(lái)的每個(gè)參數(shù)值。arguments是一個(gè)類(lèi)數(shù)組對(duì)象(不是Array的實(shí)例)

    function sayHi(name, message) {
        console.log(arguments.length);  //2
        return '小馬哥對(duì)' + name + '說(shuō)' + message;
    }

    function sayHello() {
        console.log(arguments.length);  //2
        return '小馬哥對(duì)' + arguments[0] + '說(shuō)' + arguments[1];
    }

    let sayHello2 = () => {
        return '小馬哥對(duì)' + arguments[0] + '說(shuō)' + arguments[1];
    }
    
    console.log(sayHi('韓梅梅', '今天加班'))       //小馬哥對(duì)韓梅梅說(shuō)今天加班
    console.log(sayHello('韓梅梅', '今天加班'))    //小馬哥對(duì)韓梅梅說(shuō)今天加班
    console.log(sayHello2('韓梅梅', '今天加班'))   //報(bào)錯(cuò)

箭頭函數(shù)中的參數(shù):如果函數(shù)是使用箭頭函數(shù)語(yǔ)法定義的,那么傳給函數(shù)的參數(shù)不能使用arguments關(guān)鍵字訪問(wèn),而只能通過(guò)定義的命名參數(shù)訪問(wèn)。

    function foo(){
        let sayHello = () => {
            console.log( '小馬哥對(duì)' + arguments[0] + '說(shuō)' + arguments[1]);   //小馬哥對(duì)韓梅梅說(shuō)今天加班
        }
        sayHello();
    }
    foo('李雷','你也加班');
4.沒(méi)有重載

ECMAScript函數(shù)如果定義了同名函數(shù),則后面定義的會(huì)覆蓋先定義的。

5.默認(rèn)參數(shù)值

在ECMAScript5.1及以前,實(shí)現(xiàn)默認(rèn)參數(shù)的一種常用方式就是檢測(cè)某個(gè)參數(shù)是否等于undefined。在ES6開(kāi)始可以支持顯示定義默認(rèn)參數(shù)。

   function sayName(name = '小馬哥') {
        console.log('myName==' + name);
    }
    sayName('孫紅雷');  //myName==孫紅雷
    sayName();  //myName==小馬哥
6.參數(shù)擴(kuò)展與收集

ES6新增了擴(kuò)展操作符,使用它可以非常簡(jiǎn)潔地操作和組合數(shù)據(jù)。擴(kuò)展操作符最有用的場(chǎng)景就是函數(shù)定義中的參數(shù)列表。

  • 6.1擴(kuò)展參數(shù):對(duì)于可迭代對(duì)象應(yīng)用擴(kuò)展操作符,并將其作為一個(gè)參數(shù)傳入,可以將可迭代對(duì)象拆分,并將返回的每個(gè)值單獨(dú)傳入。
    let values = [1, 2, 3, 4]
    function getSum() {
        let sum = 0;
        for (let i = 0; i < arguments.length; i++) {
            sum += arguments[i];
        }
        return sum;
    }
    console.log(getSum.apply(null, values)); //10---es5寫(xiě)法
    console.log(getSum(-1,...values,5)); //14
    console.log(getSum(...values,5,6,7,8,9,10));//55
    console.log(getSum(...values,...[5,6,7,8,9,10]));//55
    console.log(getSum(5,...values,...[5,6,7,8,9,10]));//60
  • 6.2收集參數(shù): 在構(gòu)思函數(shù)定義時(shí),可以使用擴(kuò)展操作符把不同長(zhǎng)度的獨(dú)立參數(shù)組合為一個(gè)數(shù)組。類(lèi)似于arguments對(duì)象的構(gòu)造機(jī)制,只不過(guò)收集參數(shù)的結(jié)果會(huì)得到一個(gè)Array實(shí)例。
    let ignorFirst = (firstValue, ...values) => {
        console.log(values);
    }
    ignorFirst()   // []
    ignorFirst(1,2,3,4,5)   //[2, 3, 4, 5]
7.函數(shù)內(nèi)部(arguments,this,new.target)
  • arguments對(duì)象:這個(gè)對(duì)象只有以function關(guān)鍵字定義函數(shù)時(shí)候才會(huì)有,主要用于包含函數(shù)參數(shù)。arguments還有一個(gè)callee屬性,是指向arguments對(duì)象所在函數(shù)的指針。
    function factorial(num) {
        if (num <= 1) {
            return 1;
        } else {
            return num * arguments.callee(num - 1);  //指向當(dāng)前對(duì)象所在的函數(shù)
        }
    }

    let trueFactorial = factorial;
    factorial = function () {
        return 0;
    }
    console.log(trueFactorial(5))   //120
    console.log(factorial(5))   //0
  • this對(duì)象:在標(biāo)注函數(shù)(指向調(diào)用該函數(shù)的上下文)和箭頭函數(shù)中(指向定義該函數(shù)的上下文)有不同的行為。
    在標(biāo)準(zhǔn)函數(shù)中:this引用的是把函數(shù)當(dāng)成方法調(diào)用的上下文對(duì)象,通常這個(gè)時(shí)候,稱(chēng)其為this值(在網(wǎng)頁(yè)的全局上下文中調(diào)用函數(shù)時(shí),this指向windows)。
 window.color = 'red';
    let o = {
        color: 'blue',
    }
    function sayColor() {
        console.log(this.color);
    }
    sayColor()  //red
    o.sayColor = sayColor;
    //調(diào)用的時(shí)候,函數(shù)調(diào)用者變更為o,this指向o
    o.sayColor();   //blue

在箭頭函數(shù)中:this引用的是定義箭頭函數(shù)的上下文,在事件回調(diào)或者定時(shí)回調(diào)中調(diào)用某個(gè)函數(shù),this指向的并非想要的對(duì)象。此時(shí)將回調(diào)函數(shù)寫(xiě)成箭頭函數(shù)就可以解決這個(gè)問(wèn)題。因?yàn)榧^函數(shù)中的this會(huì)保留定義該函數(shù)時(shí)的上下文。

    window.color = 'red';
    let o = {
        color: 'blue',
    }
    let sayColor = () => console.log(this.color);
    sayColor()  //red
    o.sayColor = sayColor;
    o.sayColor();   //red
  • caller屬性:這個(gè)屬性引用的是調(diào)用當(dāng)前函數(shù)的函數(shù),或者如果的在全局作用域中調(diào)用的則為null。
  function outer(){
       let  arr =[];
       for (let i=0;i<20;i++){
           arr[i] = i;
       }
       inner();
   }
   function inner(){
       let  arr =[];
       for (let i=0;i<20;i++){
           arr[i] = i;
       }
       console.log(inner.caller)  //outer的源代碼
       console.log(arguments.callee.caller) //等價(jià)于上面
   }
   outer();
  • new.target屬性(ES6新增): 檢測(cè)函數(shù)是否使用new關(guān)鍵字調(diào)用的new.target屬性。如果函數(shù)是正常調(diào)用的則new.target的值是undefined,反之將引用被調(diào)用的構(gòu)造函數(shù)。
8.函數(shù)屬性與方法(length,prototype,apply(),call())
  • length:表示該函數(shù)方法的入?yún)€(gè)數(shù)。
  • prototype:保存引用類(lèi)型所有實(shí)例方法的地方,就意味著toString()、valueOf()等方法都保存在prototype上,進(jìn)而由所有實(shí)例共享。在ES5中,prototype屬性是不可枚舉的,因此使用for-in循環(huán)不會(huì)返回這個(gè)屬性。
  • apply():這個(gè)方法都會(huì)以指定的this值來(lái)調(diào)用函數(shù),即會(huì)設(shè)置調(diào)用函數(shù)時(shí)函數(shù)體內(nèi)的this對(duì)象的值。apply()接收兩個(gè)參數(shù):函數(shù)體內(nèi)this的值和一個(gè)參數(shù)數(shù)組。第二個(gè)參數(shù)可以是Array的實(shí)例,但也可以是arguments對(duì)象。
  • call():方法作用和apply()一樣,只是傳參的形式不同,第一個(gè)參數(shù)是this,后面的參數(shù)必須一個(gè)一個(gè)列出來(lái)。
   function sum(num1,num2){
        return num1 + num2;
    }
    function sum2(num1,num2){
        return sum.apply(this,arguments)
    }
    function sum3(num1,num2){
        return sum.call(this,num1,num2);
    }
    console.log(sum2(20,30)); //50
    console.log(sum3(20,30)); //50

apply()和call(),更重要的作用是控制函數(shù)調(diào)用上下文,即函數(shù)體內(nèi)this值的能力。

window.color = 'red';
    let o = {
        color: 'blue'
    };
    function sayColor() {
        console.log(this.color);
    }
    sayColor();    //red
    sayColor.call(this);    //red
    sayColor.apply(window);    //red    
    sayColor.apply(o);    //blue
    sayColor.call(o);    //blue
9.閉包

匿名函數(shù)經(jīng)常被人誤以為是閉包。閉包指的是那些引用了另一個(gè)函數(shù)作用域變量的函數(shù),通常是在嵌套函數(shù)中實(shí)現(xiàn)的。

    function compare(propertyName) {
        return function (object1, object2) {
            //內(nèi)部函數(shù)(匿名函數(shù))引用了外部函數(shù)的變量propertyName
            let value1 = object1[propertyName];
            let value2 = object2[propertyName];
            return value1 === value2 ? 0 : value1 > value2 ? 1 : -1;
        }
    }

在這個(gè)內(nèi)部函數(shù)被返回并在其他地方被使用后,它仍然引用著哪個(gè)變量。因?yàn)檫@是因?yàn)閮?nèi)部函數(shù)的作用域鏈包含compare()函數(shù)的作用域。

10.this 對(duì)象

在閉包中使用this會(huì)讓代碼變復(fù)雜。如果內(nèi)部函數(shù)沒(méi)有使用箭頭函數(shù)定義,則this對(duì)象會(huì)在運(yùn)行時(shí)綁定到執(zhí)行函數(shù)的上下文。如果在全局函數(shù)中調(diào)用,非嚴(yán)格模式下,this等于window。

  window.identity = 'The Window';
    let object = {
        identity: 'My Object',
        getIdentityFunc() {
            return function () {
                return this.identity;
            }
        }
    }
    console.log(object.getIdentityFunc()())     //The Window

object.getIdentityFunc()返回函數(shù),所以object.getIdentityFunc()()立即調(diào)用返回的函數(shù),從而得到一個(gè)字符串。每個(gè)函數(shù)在被調(diào)用的時(shí)候都會(huì)創(chuàng)建兩個(gè)特殊的變量:this和arguments。內(nèi)部函數(shù)用于不可能直接(可以間接,箭頭函數(shù)或者使用變量)訪問(wèn)外部函數(shù)的這兩個(gè)變量。

11.立即調(diào)用的函數(shù)表達(dá)式

立即調(diào)用的函數(shù)表達(dá)式又稱(chēng)為立即嗲用的函數(shù)表達(dá)式(IIFE)。類(lèi)似于函數(shù)聲明,但是由于被包含在括號(hào)中,所以會(huì)被解釋為函數(shù)表達(dá)式。緊跟在第一組括號(hào)后面的第二組括號(hào)會(huì)立即調(diào)用前面的函數(shù)表達(dá)式。在ES5.1及以前,為了防止變量定義外泄,IIFE是個(gè)非常有效的方式。也不會(huì)導(dǎo)致閉包相關(guān)的內(nèi)存問(wèn)題,因?yàn)椴淮嬖趯?duì)這個(gè)函數(shù)的引用,為此,只要函數(shù)執(zhí)行完畢,其作作用域鏈就可以被銷(xiāo)毀。

    (function () {
        //塊級(jí)作用域
    })();
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容