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

1.箭頭函數(shù)

ES6新增屬性浇坐。箭頭函數(shù)特別適合嵌入函數(shù)的場景睬捶。

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

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

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

箭頭函數(shù)雖然語法簡介觉渴,但是很多場合不適用介劫。箭頭函數(shù)不能使用arguments、super疆拘、new.target蜕猫,也不能用作構(gòu)造函數(shù)。箭頭函數(shù)也沒有protptype屬性哎迄。

2.函數(shù)名

因為函數(shù)名就是指向函數(shù)的指針回右,所以它們跟其他包含對象指針的變量具有相同的行為。
在ES6中漱挚,所有的函數(shù)對象都會暴露一個只讀的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ù)個數(shù)蹬屹,也不關(guān)心這些參數(shù)的數(shù)據(jù)類型。定義函數(shù)時要接收2個參數(shù)白华,并不意味著調(diào)用的時候就要傳入2個參數(shù)慨默,可以傳1個,3個甚至一個都不傳弧腥。事實上厦取,在使用function關(guān)鍵字定義(非箭頭)函數(shù)時,可以在函數(shù)的內(nèi)部訪問arguments對象管搪,從中獲取傳進來的每個參數(shù)值虾攻。arguments是一個類數(shù)組對象(不是Array的實例)

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

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

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

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

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

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

5.默認參數(shù)值

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

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

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

  • 6.1擴展參數(shù):對于可迭代對象應(yīng)用擴展操作符筋夏,并將其作為一個參數(shù)傳入蒂胞,可以將可迭代對象拆分,并將返回的每個值單獨傳入条篷。
    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寫法
    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ù)組合為一個數(shù)組。類似于arguments對象的構(gòu)造機制赴叹,只不過收集參數(shù)的結(jié)果會得到一個Array實例鸿染。
    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對象:這個對象只有以function關(guān)鍵字定義函數(shù)時候才會有,主要用于包含函數(shù)參數(shù)乞巧。arguments還有一個callee屬性涨椒,是指向arguments對象所在函數(shù)的指針。
    function factorial(num) {
        if (num <= 1) {
            return 1;
        } else {
            return num * arguments.callee(num - 1);  //指向當(dāng)前對象所在的函數(shù)
        }
    }

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

在箭頭函數(shù)中:this引用的是定義箭頭函數(shù)的上下文获三,在事件回調(diào)或者定時回調(diào)中調(diào)用某個函數(shù)旁蔼,this指向的并非想要的對象。此時將回調(diào)函數(shù)寫成箭頭函數(shù)就可以解決這個問題疙教。因為箭頭函數(shù)中的this會保留定義該函數(shù)時的上下文棺聊。

    window.color = 'red';
    let o = {
        color: 'blue',
    }
    let sayColor = () => console.log(this.color);
    sayColor()  //red
    o.sayColor = sayColor;
    o.sayColor();   //red
  • caller屬性:這個屬性引用的是調(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) //等價于上面
   }
   outer();
  • new.target屬性(ES6新增): 檢測函數(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)€數(shù)耐亏。
  • prototype:保存引用類型所有實例方法的地方,就意味著toString()沪斟、valueOf()等方法都保存在prototype上广辰,進而由所有實例共享。在ES5中主之,prototype屬性是不可枚舉的择吊,因此使用for-in循環(huán)不會返回這個屬性。
  • apply():這個方法都會以指定的this值來調(diào)用函數(shù)槽奕,即會設(shè)置調(diào)用函數(shù)時函數(shù)體內(nèi)的this對象的值几睛。apply()接收兩個參數(shù):函數(shù)體內(nèi)this的值和一個參數(shù)數(shù)組。第二個參數(shù)可以是Array的實例粤攒,但也可以是arguments對象所森。
  • call():方法作用和apply()一樣,只是傳參的形式不同夯接,第一個參數(shù)是this焕济,后面的參數(shù)必須一個一個列出來。
   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)常被人誤以為是閉包逊拍。閉包指的是那些引用了另一個函數(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;
        }
    }

在這個內(nèi)部函數(shù)被返回并在其他地方被使用后顺献,它仍然引用著哪個變量旗国。因為這是因為內(nèi)部函數(shù)的作用域鏈包含compare()函數(shù)的作用域。

10.this 對象

在閉包中使用this會讓代碼變復(fù)雜注整。如果內(nèi)部函數(shù)沒有使用箭頭函數(shù)定義能曾,則this對象會在運行時綁定到執(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ù)驼唱,從而得到一個字符串。每個函數(shù)在被調(diào)用的時候都會創(chuàng)建兩個特殊的變量:this和arguments驹暑。內(nèi)部函數(shù)用于不可能直接(可以間接玫恳,箭頭函數(shù)或者使用變量)訪問外部函數(shù)的這兩個變量辨赐。

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

立即調(diào)用的函數(shù)表達式又稱為立即嗲用的函數(shù)表達式(IIFE)。類似于函數(shù)聲明京办,但是由于被包含在括號中掀序,所以會被解釋為函數(shù)表達式。緊跟在第一組括號后面的第二組括號會立即調(diào)用前面的函數(shù)表達式惭婿。在ES5.1及以前不恭,為了防止變量定義外泄,IIFE是個非常有效的方式财饥。也不會導(dǎo)致閉包相關(guān)的內(nèi)存問題换吧,因為不存在對這個函數(shù)的引用,為此钥星,只要函數(shù)執(zhí)行完畢沾瓦,其作作用域鏈就可以被銷毀。

    (function () {
        //塊級作用域
    })();
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末打颤,一起剝皮案震驚了整個濱河市暴拄,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌编饺,老刑警劉巖乖篷,帶你破解...
    沈念sama閱讀 211,348評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異透且,居然都是意外死亡撕蔼,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評論 2 385
  • 文/潘曉璐 我一進店門秽誊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鲸沮,“玉大人,你說我怎么就攤上這事锅论∷夏纾” “怎么了?”我有些...
    開封第一講書人閱讀 156,936評論 0 347
  • 文/不壞的土叔 我叫張陵最易,是天一觀的道長怒坯。 經(jīng)常有香客問我,道長藻懒,這世上最難降的妖魔是什么剔猿? 我笑而不...
    開封第一講書人閱讀 56,427評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮嬉荆,結(jié)果婚禮上归敬,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好汪茧,可當(dāng)我...
    茶點故事閱讀 65,467評論 6 385
  • 文/花漫 我一把揭開白布椅亚。 她就那樣靜靜地躺著,像睡著了一般陆爽。 火紅的嫁衣襯著肌膚如雪什往。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,785評論 1 290
  • 那天慌闭,我揣著相機與錄音,去河邊找鬼躯舔。 笑死驴剔,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的粥庄。 我是一名探鬼主播丧失,決...
    沈念sama閱讀 38,931評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼惜互!你這毒婦竟也來了布讹?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,696評論 0 266
  • 序言:老撾萬榮一對情侶失蹤训堆,失蹤者是張志新(化名)和其女友劉穎描验,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體坑鱼,經(jīng)...
    沈念sama閱讀 44,141評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡膘流,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,483評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了鲁沥。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片呼股。...
    茶點故事閱讀 38,625評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖画恰,靈堂內(nèi)的尸體忽然破棺而出彭谁,到底是詐尸還是另有隱情,我是刑警寧澤允扇,帶...
    沈念sama閱讀 34,291評論 4 329
  • 正文 年R本政府宣布缠局,位于F島的核電站,受9級特大地震影響蔼两,放射性物質(zhì)發(fā)生泄漏甩鳄。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,892評論 3 312
  • 文/蒙蒙 一额划、第九天 我趴在偏房一處隱蔽的房頂上張望妙啃。 院中可真熱鬧,春花似錦、人聲如沸揖赴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽燥滑。三九已至渐北,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間铭拧,已是汗流浹背赃蛛。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留搀菩,地道東北人呕臂。 一個月前我還...
    沈念sama閱讀 46,324評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像肪跋,于是被迫代替她去往敵國和親歧蒋。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,492評論 2 348

推薦閱讀更多精彩內(nèi)容