js函數(shù)相關(guān)基礎(chǔ)知識問答

一、問答

(一)函數(shù)聲明和函數(shù)表達式有什么區(qū)別 酝掩?

函數(shù)聲明表示方法的例子:

function printName(){
 alert("shengming");
}
printName();

函數(shù)表達式的例子:

var printName=function(){
alert("biaodashi");
}

那么他們之間有什么區(qū)別呢鳞芙?看下面的例子

console.log( shengMing );
console.log( biaodashi );
function shengMing(){
 alert("shengming")
};
var biaodashi=function biaoDaShi(){
 alert("biaodashi")
};
console.log( shengMing );
console.log( biaodashi );

運行后:

Paste_Image.png

由以上可以看出,即使聲明函數(shù)shengMing()是在后面聲明的期虾,但在前面也可調(diào)用(第一個console.log( shengMing );能夠正常運行)原朝,但是表達函數(shù)則不行(第一個console.log( biaodashi ); 運行結(jié)果顯示undefined);對于函數(shù)聲明語句镶苞,函數(shù)名稱和函數(shù)體均提前聲明了喳坠,可以在聲明之前調(diào)用它;但對于函數(shù)表達式茂蚓,只有函數(shù)變量聲明提前了壕鹉,但是函數(shù)的初始化代碼仍然在原來的位置;

(二)什么是變量的聲明前置?什么是函數(shù)的聲明前置聋涨?
  • 變量的聲明前置晾浴,是指即使我們沒有在使用變量前先聲明這個變量,但是由于變量提升(即變量聲明的前置)的存在牛郑,我們可以在聲明前使用該變量怠肋,只不過這個變量的默認值是undefined,但解析器不會報錯淹朋;例如:
Paste_Image.png
  • 同理笙各,對于函數(shù)也存在函數(shù)的聲明前置的情況,其實第一題就說明了這一點础芍,下面再舉個例子:
Paste_Image.png

當(dāng)然對于表達式函數(shù)也適用杈抢,例如下面的例子:

Paste_Image.png
(三)arguments 是什么 ?

arguments 是一個類數(shù)組對象仑性。代表傳給一個function的參數(shù)列表惶楼。
可以在函數(shù)內(nèi)部通過使用 arguments 對象來獲取函數(shù)的所有參數(shù)。這個對象為傳遞給函數(shù)的每個參數(shù)建立一個條目诊杆,條目的索引號從 0 開始歼捐。arguments 對象并不是一個真正的Array。它類似于數(shù)組晨汹,但沒有數(shù)組所特有的屬性和方法豹储,除了 length。例如淘这,它沒有 pop 方法剥扣。不過可以將其轉(zhuǎn)換成數(shù)組巩剖。另外:arguments 對象僅在函數(shù)內(nèi)部有效,在函數(shù)外部調(diào)用 arguments 對象會出現(xiàn)一個錯誤钠怯。如果你調(diào)用一個函數(shù)佳魔,當(dāng)這個函數(shù)的參數(shù)數(shù)量比它顯式聲明的參數(shù)數(shù)量更多的時候,你就可以使用 arguments 對象晦炊。這個技術(shù)對于參數(shù)數(shù)量是一個可變量的函數(shù)來說比較有用鞠鲜。 你可以用 arguments.length 來得到參數(shù)的數(shù)量,然后可以用 arguments object 來對每個參數(shù)進行處理刽锤。 (想要得到當(dāng)一個函數(shù)定義時的該函數(shù)的參數(shù)數(shù)量, 請使用 Function.length 屬性镊尺。)

arguments的屬性如下:
arguments.callee
指向當(dāng)前執(zhí)行的函數(shù)。
arguments.caller
指向調(diào)用當(dāng)前函數(shù)的函數(shù)并思。
arguments.length
指向傳遞給當(dāng)前函數(shù)的參數(shù)數(shù)量。

  • 下面舉個使用arguments的例子:
Paste_Image.png

在聲明上述函數(shù)時未使用參數(shù)语稠,即其不包含命名的參數(shù)宋彼,這說明在函數(shù)中命名的參數(shù)只提供便利,但不是必須的仙畦。

  • 下面再舉個使用arguments.length的例子:
Paste_Image.png
(四)函數(shù)的重載怎樣實現(xiàn) 输涕?

由于js不能像傳統(tǒng)意義上那樣實現(xiàn)重載,因此我們可以通過使用arguments的方法實現(xiàn)非完美的重載慨畸;

如下面的例子:

Paste_Image.png
(五)立即執(zhí)行函數(shù)表達式是什么莱坎?有什么作用 ?

類似于

Paste_Image.png

類似于上述函數(shù)的寫法叫做「立即執(zhí)行函數(shù)」也叫「自執(zhí)行匿名函數(shù)」(self-executing anonymous function)寸士;「立即執(zhí)行函數(shù)表達式」(Immediately-Invoked Function Expression檐什,簡稱IIFE);
其中一般推薦使用第一種寫法弱卡,但是目前很多比較好的js library 使用的都是第二種方式乃正。 比如: web 圖形繪制的: git , draw2d ,....

(六)什么是函數(shù)的作用域鏈忠荞?

函數(shù)對象和其他對象一樣蒋歌,擁有可以通過代碼訪問的屬性和一系列供js引擎訪問的內(nèi)部屬性帅掘,其中一個內(nèi)部屬性是[scope],該屬性包括了函數(shù)被創(chuàng)建的作用域中的對象集合堂油,這個集合稱為函數(shù)的作用域鏈修档,它決定了哪些能夠被函數(shù)訪問;

舉個例子:

Paste_Image.png

二府框、代碼

1.以下代碼輸出什么吱窝?
    function getInfo(name, age, sex){
        console.log('name:',name);
        console.log('age:', age);
        console.log('sex:', sex);
        console.log(arguments);
        arguments[0] = 'valley';
        console.log('name', name);
    }

    getInfo('hunger', 28, '男');
    getInfo('hunger', 28);
    getInfo('男');

運行結(jié)果會如下:

    /*  getInfo('hunger', 28, '男')運行結(jié)果:

        name:hunger
        age:28
        sxe:男
        {valley, 28, 男}
        name valley
 
    */


    /*   getInfo('hunger', 28)運行結(jié)果:

        name:hunger
        age:28
        sxe:undefind
        {valley,28}
        name valley


    */

    /*   getInfo('男')運行結(jié)果:

        name:男
        age:undefind
        sxe:undefind
        {valley}
        name valley


    */
Paste_Image.png
2.寫一個函數(shù),返回參數(shù)的平方和迫靖?如
   function sumOfSquares(){
   }
   sumOfSquares(2,3,4);   // 29
   sumOfSquares(1,3);   // 10
function sumOfSquares(){
        for (var i = 0,x = 0; i < arguments.length; i++) {
            x=x+arguments[i]*arguments[i];          
         }
        console.log(x);
    }
Paste_Image.png
3.如下代碼的輸出院峡?為什么 ?
    console.log(a);
    var a = 1;
    console.log(b);

上述代碼相當(dāng)于:

    var a;
    console.log(a);
    a = 1;
    console.log(b);

輸出為 undefined;b is not defined; 由于變量提升的存在,導(dǎo)致console.log(a)時系宜,不會出現(xiàn)a is not defined照激,但是由于console.log(a)之前a未賦值,所以才會導(dǎo)致出現(xiàn) undefined盹牧; 而對于console.log(b)語句俩垃,由于b既未聲明也未賦值,所以才會報錯b is not defined錯誤汰寓;

Paste_Image.png
4.如下代碼的輸出口柳?為什么 ?
    sayName('world'); //hello world (解釋:該函數(shù)為聲明函數(shù),存在提前聲明的情況有滑;)
    sayAge(10);/*sayAge is not a function (解釋:該函數(shù)為表達式函數(shù)跃闹,
不存在提前聲明的情況,所以會報錯)*/
    function sayName(name){
        console.log('hello ', name);
    }
    var sayAge = function(age){
        console.log(age);
    };

上述代碼相當(dāng)于:

var sayAge毛好;
    function sayName(name){
        console.log('hello ', name);
    }
    sayName('world');
    sayAge(10);// sayAge is not a function 
 sayAge = function(age){
        console.log(age);
    };
Paste_Image.png
5.如下代碼的輸出望艺?為什么 ?
    function fn(){}
    var fn = 3;
    console.log(fn);//3

上述代碼相當(dāng)于:

     var fn; //fn 此時為普通變量
    function fn(){}    //fn此時為函數(shù)名
    fn = 3;  /*fn此時值等于3,因為在同一個作用域內(nèi)定義了名字相同的變量和方法的話睛榄,無論其順序如
何荣茫,變量的賦值會覆蓋方法的賦值;*/
    console.log(fn); //打印時輸出3
Paste_Image.png
6.如下代碼的輸出场靴?為什么 ?
    function fn(fn2){
       console.log(fn2);
       var fn2 = 3;
       console.log(fn2);
       console.log(fn);
       function fn2(){
            console.log('fnnn2');
        }
     }
    fn(10);

上述代碼相當(dāng)于:

    function fn(fn2){
       var fn2啡莉;
       function fn2(){
            console.log('fnnn2');
        }
       console.log(fn2);   //
/* 由于同個作用域下,變量聲明和函數(shù)聲明存在命名沖突時旨剥,變量聲明前置要比函數(shù)聲明前置的優(yōu)先級底咧欣,因此此時打印出的是函數(shù)*/
       fn2 = 3;
       console.log(fn2); //3   
   /*此時fn2被賦值3了,因為在同一個作用域中轨帜,定義了同一個名字的變量
和方法時魄咕,無論順序如何,變量的賦值會覆蓋方法的賦值*/
       console.log(fn); //  此時會打印函數(shù)fn本身 

     }
    fn(10);

因此結(jié)果為

Paste_Image.png

如果將此題改成下面的代碼蚌父,結(jié)果將是怎樣的呢哮兰?

    function fn(fn2){
       var fn2=200;
       function fn2(){
            console.log('fnnn2');
        }

       console.log(fn2);
       var fn2 = 3;
       console.log(fn2);

     }
    fn(10);

其實上面的代碼相當(dāng)于

    function fn(fn2){
       var fn2=200;
       function fn2(){
            console.log('fnnn2');
        }

       console.log(fn2); //200 此時并沒有輸出函數(shù)fn2毛萌,為什么呢?
/*因為同一個作用域中喝滞,定義了名字相同的變量和方法的話阁将,無論順序如何
變量的賦值會覆蓋方法的賦值;
*/
       var fn2 = 3;
       console.log(fn2); //3

     }
    fn(10);

輸出結(jié)果:

Paste_Image.png

如果再將代碼改成:

    function fn(fn2){
        var fn2=200;
       function fn2(){
            console.log('fnnn2');
        }

       console.log(fn2);
        fn2 = 3;
       console.log(fn2);

     }
    fn(10);
    console.log(fn2); //此處會報錯右遭,因為由于函數(shù)作用域的存在做盅,此處的fn2并未定義變量且賦值;

則結(jié)果為

Paste_Image.png
7.如下代碼的輸出窘哈?為什么?
    var fn = 1;
    function fn(fn){
         console.log(fn); 
    }
    console.log(fn(fn)); 

上述代碼相對于

    var fn ;
    
    function fn(fn){
         console.log(fn); 
    };
    fn = 1;
    console.log(fn(fn)); //報錯 fn  is not a function
/* 由于同一個作用域中吹榴,定義同一個名字的變量和方法時,變量賦值會覆蓋方法的賦值滚婉,因此此時解析器
并不能夠識別fn為函數(shù)图筹,但是在打印時又以函數(shù)的方式打印,因此會報錯*/

其實上面的例子可簡化成這樣的理解

Paste_Image.png

打印a(a) 满哪,解析器會把它當(dāng)作成要打印一個函數(shù)婿斥,但是a并不是一個函數(shù),因此會報錯哨鸭。

8.如下代碼的輸出?為什么 ?
    //作用域
    console.log(j); 
    console.log(i); 
    for(var i=0; i<10; i++){
        var j = 100;
    }
    console.log(i); 
    console.log(j); 

其實上面的代碼相當(dāng)于

   var j ;
   var i ;
    console.log(j);  // undefined 
/*解釋:由于變量提升的存在娇妓,導(dǎo)致此處提示j未被賦值像鸡,但不抱錯*/
    console.log(i); //undefined 
/*解釋:同理,由于變量提升的存在哈恰,
導(dǎo)致此處提示i未被賦值只估,但不抱錯*/
    for(var i=0; i<10; i++){
        var j = 100;
    }
    console.log(i); //10 (解釋:for語句執(zhí)行完后,i值為10)
    console.log(j); // 100 (解釋:for語句執(zhí)行完后着绷,j值為100)
Paste_Image.png
9.如下代碼的輸出蛔钙?為什么 ?
    fn();
    var i = 10;
    var fn = 20;
    console.log(i);
    function fn(){
        console.log(i); 
        var i = 99;
        fn2();  
        console.log(i); 
        function fn2(){
            i = 100;
        }
    }

上述代碼相當(dāng)于:

    var i;
    var fn;
    function fn(){
        var i;
        function fn2(){
            i = 100;
        }
        console.log(i);  //undefinded
/*此時i并未被賦值,因此為undefinded*/
        var i = 99;
        fn2(); //執(zhí)行后i為100荠医;
        console.log(i);  //100
/*此時打印i吁脱,i的值為100*/

    }

    fn();
    var i = 10;
    var fn = 20;
    console.log(i); //10 
/*雖然i在function內(nèi)部為100但由于函數(shù)作用域的存在及i的外部賦值,在外部的為10彬向;*/

Paste_Image.png
10.如下代碼的輸出兼贡?為什么?
    var say = 0;
    (function say(n){ 
        console.log(n);

        if(n<3) return; 
        say(n-1);
    }( 10 )); //輸出 10,9,8,7,6,5,4,3,2
/*該函數(shù)為立即執(zhí)行函數(shù),因此會馬上執(zhí)行娃胆,當(dāng)n為2時遍希,因為2<3,因此會立即跳出該函數(shù)*/
    console.log(say); //輸出0  
/*因為在該作用域中里烦,變量say已經(jīng)被賦值了0凿蒜,在同一個作用域中禁谦,變量和方法同名時,無論順序如何废封,
變量的賦值會覆蓋方法的賦值州泊,更何況say()為立即執(zhí)行函數(shù);
*/
Paste_Image.png

如果將題中代碼改成

    var say = 0;
    var n=10086;
    function say(n){ 
        console.log(n); 
        if(n<3) return; 
        say(n-1);
    };
    console.log(say(n)); 
    console.log(say(n));   /*此時解析器以為要執(zhí)行say(n)函數(shù)虱饿,但由于同一個作用域下拥诡,若存在同
名的變量和方法,變量的賦值會覆蓋方法的賦值氮发,因此say還是被看成值為0的變量渴肉,而say(n)又不是一個函
數(shù),因此會報錯說say不是一個函數(shù)
*/

上述代碼執(zhí)行后將會報錯爽冕。

Paste_Image.png

補充:作用域鏈相關(guān)資料

**本文版權(quán)歸本人即簡書筆名:該賬戶已被查封 所有仇祭,如需轉(zhuǎn)載請注明出處。謝謝颈畸! *

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末乌奇,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子眯娱,更是在濱河造成了極大的恐慌礁苗,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,839評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件徙缴,死亡現(xiàn)場離奇詭異试伙,居然都是意外死亡,警方通過查閱死者的電腦和手機于样,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評論 2 382
  • 文/潘曉璐 我一進店門疏叨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人穿剖,你說我怎么就攤上這事蚤蔓。” “怎么了糊余?”我有些...
    開封第一講書人閱讀 153,116評論 0 344
  • 文/不壞的土叔 我叫張陵秀又,是天一觀的道長。 經(jīng)常有香客問我啄刹,道長涮坐,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,371評論 1 279
  • 正文 為了忘掉前任誓军,我火速辦了婚禮袱讹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己捷雕,他們只是感情好椒丧,可當(dāng)我...
    茶點故事閱讀 64,384評論 5 374
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著救巷,像睡著了一般壶熏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上浦译,一...
    開封第一講書人閱讀 49,111評論 1 285
  • 那天棒假,我揣著相機與錄音,去河邊找鬼精盅。 笑死帽哑,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的叹俏。 我是一名探鬼主播妻枕,決...
    沈念sama閱讀 38,416評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼粘驰!你這毒婦竟也來了屡谐?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,053評論 0 259
  • 序言:老撾萬榮一對情侶失蹤蝌数,失蹤者是張志新(化名)和其女友劉穎愕掏,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體顶伞,經(jīng)...
    沈念sama閱讀 43,558評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡亭珍,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,007評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了枝哄。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,117評論 1 334
  • 序言:一個原本活蹦亂跳的男人離奇死亡阻荒,死狀恐怖挠锥,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情侨赡,我是刑警寧澤蓖租,帶...
    沈念sama閱讀 33,756評論 4 324
  • 正文 年R本政府宣布,位于F島的核電站羊壹,受9級特大地震影響蓖宦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜油猫,卻給世界環(huán)境...
    茶點故事閱讀 39,324評論 3 307
  • 文/蒙蒙 一稠茂、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦睬关、人聲如沸诱担。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,315評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽蔫仙。三九已至,卻和暖如春丐箩,著一層夾襖步出監(jiān)牢的瞬間摇邦,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,539評論 1 262
  • 我被黑心中介騙來泰國打工屎勘, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留施籍,地道東北人。 一個月前我還...
    沈念sama閱讀 45,578評論 2 355
  • 正文 我出身青樓挑秉,卻偏偏與公主長得像法梯,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子犀概,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,877評論 2 345

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