饑人谷-任務(wù)十七

一顷编、函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別 (*)

主要區(qū)別函數(shù)聲明會有聲明提升堕义,而函數(shù)表達(dá)式的規(guī)則跟變量一樣上陕。
例:
源碼:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
<script>
foo1(4);
foo2(3);
var foo2 = function(a){console.log(a)}
function foo1(i){console.log(i)}
</script>
</body>
</html>

相當(dāng)于:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
<script>
var foo2;//----變量提升
function foo1(i){console.log(i)};//---函數(shù)聲明提升
foo1(4);//----可執(zhí)行該函數(shù)
foo2(3);//----會報錯扬跋,因為是從上到下的順序的
foo2 = function(a){console.log(a)}
</script>
</body>
</html>
運(yùn)行結(jié)果

二阶捆、什么是變量的聲明前置?什么是函數(shù)的聲明前置 (**)

具體例子可以看第一道題已經(jīng)po出demo钦听;
JavaScript引擎的工作方式是洒试,先解析代碼,獲取所有被聲明的變量朴上,然后再一行一行地運(yùn)行垒棋。這造成的結(jié)果,就是所有的變量的聲明語句痪宰,都會被提升到代碼的頭部叼架,這就叫做變量提升(hoisting)畔裕。
函數(shù)的聲明前置就是把整個函數(shù)提升到當(dāng)前作用域的最前面(位于前置的變量聲明后面)。

三乖订、arguments 是什么 (*)

arguments 是一個類數(shù)組對象扮饶。代表傳給一個function的參數(shù)列表。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
  <script>
function demo() {
  for(var i=0; i<arguments.length; i++)
  console.log(arguments[i]);
  console.log(arguments.length);
}

demo("a",2,3,4,5);
  </script>
</body>
</html>

arguments.png

四乍构、函數(shù)的重載怎樣實現(xiàn) (**)

  • 什么是重載函數(shù)允許在同一范圍中聲明幾個功能類似的同名函數(shù)甜无,但是這些同名函數(shù)的形式參數(shù)必須不同,這就是重載函數(shù)哥遮。

  • 重載函數(shù)的作用重載函數(shù)常用來實現(xiàn)功能類似而所處理的數(shù)據(jù)類型不同的問題岂丘。

  • JS的函數(shù)重載的實現(xiàn)在面向?qū)ο笳Z言里重載是很重要的一個特性,而JavaScript這個自稱面向?qū)ο蟮恼Z言是沒有直接提供重載眠饮。那么JavaScript是怎么實現(xiàn)(準(zhǔn)確地講應(yīng)該叫“模擬”)的呢奥帘?

  • 利用arguments實現(xiàn)重載arguments是JavaScript里的一個內(nèi)置對象,包含了調(diào)用者傳遞的實際參數(shù)君仆,而調(diào)用時只它和數(shù)組一樣有個length屬性翩概;我們暫且把它當(dāng)“數(shù)組”來理解吧,我們根據(jù)該數(shù)組的長度以及其元素的類型來選擇不同的實現(xiàn)返咱,從而模擬了重載钥庇。

在JavaScript中沒有函數(shù)重載的概念,函數(shù)通過名字確定唯一性咖摹,參數(shù)不同也被認(rèn)為是相同的函數(shù)评姨,后面的覆蓋前面的。所以我們這里通過arguments實現(xiàn)重載:

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>JS Bin</title>
</head>
<body>
<script>
function demo() {
  for(var i=0; i<arguments.length; i++)
  console.log(arguments[i]);
}

demo(2,3,4,5);
demo("a","b");
</script>
</body>
</html>

重載.png

五萤晴、立即執(zhí)行函數(shù)表達(dá)式是什么吐句?有什么作用 (***)

  • 立即執(zhí)行函數(shù)表達(dá)式(IIFE——Immediately Invoked Function Expression),是將函數(shù)的定義放在一個圓括號里店读,讓JavaScript引擎將其理解為一個表達(dá)式嗦枢,再在函數(shù)的定義后面加一個(),以達(dá)到定義函數(shù)后立即調(diào)用該函數(shù)的效果屯断。下面兩種形式在功能上是一致的:
(function(){ /* code */ }()); //立即執(zhí)行函數(shù)表達(dá)式
(function(){ /* code */ })(); //立即執(zhí)行函數(shù)表達(dá)式

  • 立即執(zhí)行函數(shù)表達(dá)式的作用
    • 可以創(chuàng)建匿名函數(shù)文虏,避免污染全局變量
    • 防止其他js文件出現(xiàn)與本文件的函數(shù)名重名情況,那么函數(shù)內(nèi)部定義的 同一個變量a有可能被污染;
    • 形成一個單獨的作用域殖演,可以封裝一些外部無法讀取的私有變量
// 寫法一
var tmp = newData;
  processData(tmp);
  storeData(tmp);// 
寫法二(function (){ 
  var tmp = newData; 
  processData(tmp); 
  storeData(tmp);
}());

上面代碼中氧秘,寫法二比寫法一更好,因為完全避免了污染全局變量

六趴久、什么是函數(shù)的作用域鏈 (****)

解釋:
當(dāng) Javascript 代碼需要查詢一個變量 x 的時候丸相,會有一個被稱為「變量名解析」的過程。它會首先檢查作用域鏈的第一個對象彼棍,如果這個對象包含名為 x 的屬性灭忠,那么就采用這個屬性的值膳算,否則,會繼續(xù)檢查第二個對象更舞,依此類推畦幢。當(dāng)檢查到最后一個對象的時候仍然沒有相應(yīng)的屬性,則這個變量會被認(rèn)定為是「未定義」的缆蝉。
舉例:

<script type="text/javascript">
    var rain = 1;
    function rainman(){
        var man = 2;
        function inner(){
            var innerVar = 4;
            alert(rain);
        }
        inner();    //調(diào)用inner函數(shù)
    }
    rainman();    //調(diào)用rainman函數(shù)
</script>

觀察alert(rain);這句代碼宇葱。JavaScript首先在inner函數(shù)中查找是否定義了變量rain,如果定義了則使用inner函數(shù)中的rain變量刊头;如果inner函數(shù)中沒有定義rain變量黍瞧,JavaScript則會繼續(xù)在rainman函數(shù)中查找是否定義了rain變量,在這段代碼中rainman函數(shù)體內(nèi)沒有定義rain變量原杂,則JavaScript引擎會繼續(xù)向上(全局對象)查找是否定義了rain印颤;在全局對象中我們定義了rain = 1,因此最終結(jié)果會彈出'1'穿肄。

上面的代碼涉及到了三個作用域鏈對象年局,依次是:inner、rainman咸产、window矢否。

參考資料1
參考資料2

七、代碼題

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('男');
17.1.png

2、寫一個函數(shù)屑彻,返回參數(shù)的平方和验庙?如 (難度**)
利用arguments類數(shù)組對象實現(xiàn);

   function sumOfSquares(){
        var result=0;
        for(var i=0; i<arguments.length; i++){
                 result += arguments[i]*arguments[i];       
         }
        console.log(result);
   }
   sumOfSquares(2,3,4);   // 29
   sumOfSquares(1,3);   // 10
17-2.png

3社牲、如下代碼的輸出粪薛?為什么 (難度*)
源碼:

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

可看做:

    var a; //--------變量提升
    console.log(a);//----log.undefined
    a = 1;//---------賦值a
    console.log(b);//------log.報錯

4、如下代碼的輸出搏恤?為什么 (難度*)
源碼:

   sayName('world');
    sayAge(10);
    function sayName(name){
        console.log('hello ', name);
    }
    var sayAge = function(age){
        console.log(age);
    };

可看做:

    var sayAge;//-------變量聲明提升
    function sayName(name){---------函數(shù)聲明提升
        console.log('hello ', name);//----log. "hello,world"
    }
    sayName('world');//---調(diào)用函數(shù)
    sayAge(10);
    sayAge = function(age){
        console.log(age);//--------log.報錯汗菜,無此函數(shù);因為sayAge(10)無法調(diào)用挑社;
    };

5、 如下代碼的輸出巡揍?為什么 (難度**)
源碼:

   function fn(){}
    var fn = 3;
    console.log(fn);

可看做:

    var fn;
    function fn(){}
    fn = 3;
    console.log(fn);//-------log.3
    命名沖突:函數(shù)的聲明會覆蓋變量的聲明痛阻,變量的賦值會覆蓋函數(shù)的賦值;

6腮敌、 如下代碼的輸出阱当?為什么 (難度***)

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

可看做:

    function fn(fn2){
    var fn2 = 10;//---傳參數(shù)給fn2賦值10
    var fn2;//----變量聲明提升
    function fn2(){  //----函數(shù)提升,覆蓋變量fn2變?yōu)楹瘮?shù)
            console.log('fnnn2');//--無俏扩,沒有調(diào)用
        }
    console.log(fn2);//-----log.fn2函數(shù)
    fn2 = 3;
    console.log(fn2);//-----3
    console.log(fn);//------log.fn函數(shù)
    }
 fn(10)

console.log('fnnn2'):因為沒有調(diào)用fn2函數(shù)所有沒有執(zhí)行;

第一個console.log(fn2);顯示是fn2函數(shù)弊添,由于傳進(jìn)去的參數(shù)fn2=10被聲明為變量后又被函數(shù)fn2給覆蓋了录淡,故log出的就是fn2函數(shù);

第一個console.log(fn2);顯示的是fn函數(shù)油坝,首先會檢查作用域鏈的第一個調(diào)用對象嫉戚,沒有找到fn該屬性則去找第二個對象即全局對象,找到fn的屬性是一個函數(shù)澈圈,故log.出的是fn()函數(shù)彬檀;

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)); //--------報錯

根據(jù)命名沖突窍帝,執(zhí)行console.log(fn(fn))時,fn為變量類型诽偷,值為1坤学,所以報錯,fn不為函數(shù)报慕。

8深浮、如下代碼的輸出?為什么 (難度**)

源碼:

    //作用域
    console.log(j);
    console.log(i);
    for(var i=0; i<10; i++){
        var j = 100;
    }
    console.log(i);
    console.log(j);

可看做:

    var i;
    var j;
    console.log(j);//---log.undefined
    console.log(i);//---log.undefined
    for(i=0; i<10; i++){
         j = 100;
    }
    console.log(i);//----log.10
    console.log(j);//----log.100

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;
        }
    }

可看做:

    var i 
    var fn
     function fn(){
            var i;
            function fn2(){
                i = 100;
            }
            console.log(i);//----log.undefined
            i = 99;
            fn2();
            console.log(i); //----log.100         
        }
    fn();
    i = 10;
    fn = 20;
    console.log(i);//---log.10

第一條console.log(i):由于變量聲明前置,但是還沒初始化洋闽,所以輸出的是undefined玄柠;
第二條console.log(i):先將i賦值為99,然后調(diào)用fn2()函數(shù)诫舅,執(zhí)行函數(shù)i = 100, 因在本層fn2()調(diào)用對象內(nèi)沒有檢索到聲明羽利,故尋下一層,下一層將i聲明為變量刊懈,故作用再了這層作用域內(nèi)这弧,也就是在fn()這個調(diào)用對象里面;所以i輸出100虚汛;
第三條console.log(i):因fn()調(diào)用對象內(nèi)i為局部變量匾浪,是不會影響到外界的,所以i檢索全局變量的值卷哩,i輸出10蛋辈;

10、如下代碼的輸出?為什么 (難度*****)

    var say = 0;
    (function say(n){
        console.log(n);
        if(n<3) return;
        say(n-1);
    }( 10 ));
    console.log(say);

輸出: 10 9 8 7 6 5 4 3 2//到2這里就跳出冷溶; 0
在立即執(zhí)行函數(shù)say(n)中渐白,if,return和say(n-1)組成了一個循環(huán)逞频,從n的傳遞參數(shù)10開始纯衍,計算結(jié)果分別為10,9,8,7,6,5,4,3,2,當(dāng)n為2時苗胀,首先console.log襟诸,然后發(fā)現(xiàn)n<3,循環(huán)退出柒巫;
由于(function say(n){console.log(n);if(n<3) return;say(n-1); }( 10 ));這個是立即執(zhí)行函數(shù)励堡,故這可以看作是一個封閉的不受外界影響也不影響外界的局部作用域,所以全局console.log(say);輸出0

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末堡掏,一起剝皮案震驚了整個濱河市应结,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌泉唁,老刑警劉巖鹅龄,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異亭畜,居然都是意外死亡扮休,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門拴鸵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來玷坠,“玉大人,你說我怎么就攤上這事劲藐“吮ぃ” “怎么了?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵聘芜,是天一觀的道長兄渺。 經(jīng)常有香客問我,道長汰现,這世上最難降的妖魔是什么挂谍? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮瞎饲,結(jié)果婚禮上口叙,老公的妹妹穿的比我還像新娘。我一直安慰自己嗅战,他們只是感情好庐扫,可當(dāng)我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般形庭。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上厌漂,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天萨醒,我揣著相機(jī)與錄音,去河邊找鬼苇倡。 笑死富纸,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的旨椒。 我是一名探鬼主播晓褪,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼综慎!你這毒婦竟也來了涣仿?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤示惊,失蹤者是張志新(化名)和其女友劉穎好港,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體米罚,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡钧汹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了录择。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拔莱。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖隘竭,靈堂內(nèi)的尸體忽然破棺而出塘秦,到底是詐尸還是另有隱情,我是刑警寧澤货裹,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布嗤形,位于F島的核電站,受9級特大地震影響弧圆,放射性物質(zhì)發(fā)生泄漏赋兵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一搔预、第九天 我趴在偏房一處隱蔽的房頂上張望霹期。 院中可真熱鬧,春花似錦拯田、人聲如沸历造。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽吭产。三九已至侣监,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間臣淤,已是汗流浹背橄霉。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留邑蒋,地道東北人姓蜂。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像医吊,于是被迫代替她去往敵國和親钱慢。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,611評論 2 353

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

  • 函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別 (*)解析器會率先讀取函數(shù)聲明卿堂,并使其在執(zhí)行任何代碼之前可以訪問束莫;函數(shù)表達(dá)式則必須...
    coolheadedY閱讀 388評論 0 1
  • 1.函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別 (*) 區(qū)別: 函數(shù)聲明后面的分號可加可不加,不加也不影響接下來語句的執(zhí)行御吞,但...
    Sheldon_Yee閱讀 399評論 0 1
  • 工廠模式類似于現(xiàn)實生活中的工廠可以產(chǎn)生大量相似的商品麦箍,去做同樣的事情,實現(xiàn)同樣的效果;這時候需要使用工廠模式陶珠。簡單...
    舟漁行舟閱讀 7,750評論 2 17
  • 問答題 函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別 (*)答://函數(shù)聲明function hello(){ conso...
    饑人谷_桶飯閱讀 245評論 0 0
  • 全球(中國)旗袍總會/華太俱樂部 一件華美旗袍?還是一副窈窕倩影暑脆?抑或是一身令歲月難擋的優(yōu)雅渠啤? 由全球(中國)旗袍...
    華太俱樂部閱讀 403評論 0 0