任務(wù)十七~函數(shù)

問答部分

一兴喂、函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別蔼囊?

  • 二者表示函數(shù)的方式不一樣,如下
  • 函數(shù)聲明(函數(shù)名稱不可少)
function funName(){
              statement;
          }
  • 函數(shù)表達(dá)式(函數(shù)名稱可以沒有衣迷,末尾有一個(gè)分號)
var funName = function(){
             statement;
         };
  • 二者在函數(shù)名提升的時(shí)候不一樣(函數(shù)名提升是指JS引擎在解析代碼時(shí)畏鼓,整個(gè)函數(shù)會像變量提升一樣提到代碼頭部,但此時(shí)并未執(zhí)行
  • 對于函數(shù)聲明蘑险,如下代碼
printName("jirengu");
function printName(name){
       console.log(name);
  }

此時(shí)顯示的結(jié)果如下圖所示

函數(shù)名提升

此時(shí)執(zhí)行調(diào)用函數(shù)時(shí)不會報(bào)錯(cuò)滴肿,因?yàn)楹瘮?shù)名的提升,整個(gè)函數(shù)被提升到代碼頭部

  • 對于函數(shù)表達(dá)式佃迄,如下代碼
printName("jirengu");
var printName = function(name){
          console.log(name);
 }泼差;

此時(shí)顯示結(jié)果如下圖所示


函數(shù)表達(dá)式

這個(gè)時(shí)候會報(bào)錯(cuò)是因?yàn)榇藭r(shí)JS引擎是如下處理代碼的

var printName;
printName("jirengu");
printName = function(name){
            console.log(name);
   }贵少;

以上代碼中,第一行表示函數(shù)變量聲明提前堆缘,但還未被賦值滔灶,等于undefined;所以在執(zhí)行第二行時(shí)則會發(fā)生錯(cuò)誤吼肥;即函數(shù)表達(dá)式只是函數(shù)聲明提前录平,但是函數(shù)部分并未提前


二、什么是變量的聲明前置缀皱?什么是函數(shù)的聲明前置斗这?

  • 變量的聲明前置是指Javascript引擎解析代碼,獲取所有被聲明的代碼變量啤斗,然后再一行一行的執(zhí)行表箭。這樣造成的結(jié)果是所有變量的聲明語句,都將被提升到代碼頭部钮莲,如下情況
console.log(a);
var a = 1;

此時(shí)并不會報(bào)錯(cuò)免钻,結(jié)果如下圖所示


變量的聲明前置

JS引擎在解析代碼時(shí)相當(dāng)于以下過程

var a;//變量聲明提升到代碼頭部
console.log(a);
a = 1;
  • 函數(shù)聲明前置指JS引擎在解析代碼時(shí),整個(gè)函數(shù)會像變量提升一樣提到代碼頭部崔拥,如下情況
printNumber(12);
function printNumber(num){
    console.log(num);
 }

此時(shí)不會報(bào)錯(cuò)极舔,顯示結(jié)果如下圖所示


函數(shù)聲明前置

此過程相當(dāng)于一下代碼

function printNumber(num){
    console.log(num);
 }//函數(shù)聲明前置會讓整個(gè)函數(shù)提到代碼頭部
printNumber(12);

還有函數(shù)表達(dá)式的前置,見問題1


三链瓦、arguments 是什么拆魏?

  • arguments~函數(shù)運(yùn)行時(shí),有時(shí)需要提供外部數(shù)據(jù)慈俯,不同的外部數(shù)據(jù)會得到不同的結(jié)果稽揭,這種外部數(shù)據(jù)即為參數(shù),比如如下代碼
function getSquare(x){
     return x * x;
}
console.log(getSquare(4));//16

其中x即為getSquare函數(shù)的參數(shù)肥卡,每次運(yùn)行g(shù)etSquare函數(shù)時(shí),都要提供x值事镣,否則不會得到結(jié)果

  • arguments不是必須的步鉴,JS中允許省略arguments,被省略的參數(shù)的值就變?yōu)閡ndefined
  • 函數(shù)體內(nèi)可以通過arguments對象來訪問這個(gè)數(shù)組,從而獲取傳遞給函數(shù)的每一個(gè)參數(shù)璃哟,如下代碼
function visitArg(){
                console.log(arguments[0]);
                console.log(arguments[1]);
                console.log(arguments[2]);
            }
 visitArg("ji","ren","gu");

顯示結(jié)果如下圖


arguments對象獲取函數(shù)的參數(shù)
  • 通過訪問arguments對象的length屬性可以獲知有多少個(gè)參數(shù)傳遞給了函數(shù)氛琢,如下
function howmanyArg(){
     console.log(arguments.length);
}
howmanyArg(1,2,3,4);
howmanyArg(12);
howmanyArg();
howmanyArg("hello",4,false);

輸出結(jié)果為下圖所示


arguments.length

四、函數(shù)的重載怎樣實(shí)現(xiàn)随闪?

  • 在一些語言中(如Java)中阳似,相同名字的函數(shù)參數(shù)個(gè)數(shù)不同或者順序不同都被認(rèn)為是不同的函數(shù),稱為函數(shù)重載铐伴。但是在Javascript中沒有函數(shù)的重載
  • 在Javascript中可以通過arguments來實(shí)現(xiàn)函數(shù)的重載撮奏,如下代碼
function sum(){
    var x = 0;
    for(var i = 0;i < arguments.length;i++){
             x += arguments[i];
     }
     return x;
  }
  console.log(sum(1,2,3));//6

五俏讹、立即執(zhí)行函數(shù)表達(dá)式是什么?有什么作用 畜吊?

  • 立即執(zhí)行函數(shù)模式(沒有聲明前置)是一種語法泽疆,可以讓你的函數(shù)在定義后立即被執(zhí)行,這種模式本質(zhì)上就是函數(shù)表達(dá)式(命名的或者匿名的)玲献,在創(chuàng)建后立即執(zhí)行殉疼,其代碼格式如下
//在最前最后加括號
(function atOnce(){
           console.log("abc");
}());
//在function外面加括號
(function atOnce(){
           console.log("abc");
})();
  • 立即執(zhí)行函數(shù)表達(dá)式的作用:
  • 立即執(zhí)行函數(shù)模式被廣泛使用,它可以幫你封裝大量的工作而不會在背后遺留任何全局變量
  • 定義的所有變量都會成員立即執(zhí)行函數(shù)的局部變量捌年,所以你不用擔(dān)心這些臨時(shí)變量會污染全局空間
  • 這種模式經(jīng)常被使用在書簽工具(bookmarklets)中瓢娜,因?yàn)闀灩ぞ咴谌魏雾撁嫔线\(yùn)行并且保持全局命名空間干凈是非常必要的
  • 這種模式也可以讓你將獨(dú)立的功能封裝在自包含模塊中
    更多知識

六、什么是函數(shù)的作用域鏈礼预?

  • 函數(shù)的作用域鏈~任何程序設(shè)計(jì)語言都有作用域的概念眠砾,簡單的說,作用域就是變量與函數(shù)的可訪問范圍逆瑞,即作用域控制著變量與函數(shù)的可見性和生命周期荠藤。在JavaScript中,變量的作用域有全局作用域和局部作用域兩種
  • 全局作用域~在代碼中任何地方都能訪問到的對象擁有全局作用域获高,一般來說以下幾種情形擁有全局作用域
  • 最外層函數(shù)和在最外層函數(shù)外面定義的變量擁有全局作用域哈肖,如下
var num = 1;
function example(){
  var ourAuthor = "jirengu";
  function printName(){
      console.log(ourAuthor);
  }
  printName();
 }
//在這段代碼中,變量num和函數(shù)example是擁有全局作用域念秧;
而在函數(shù)example里面的變量和函數(shù)并不擁有全局作用域
  • 所有末定義直接賦值的變量自動聲明為擁有全局作用域淤井,如下
 function example(){
 var a = "jirengu";
 b ="quanju";
 console.log(a);
}
//在以上代碼中,變量b擁有全局作用域摊趾;而變量a則不是
  • 所有window對象的屬性擁有全局作用域
  • 局部作用域~和全局作用域相反币狠,局部作用域一般只在固定的代碼片段內(nèi)可訪問到,最常見的例如函數(shù)內(nèi)部砾层,所有在一些地方也會看到有人把這種作用域稱為函數(shù)作用域
  function example(){
    var author = "jirengu";
    function printName(){
        console.log(ourAuthor);
    }
    printName();
   }
//在以上代碼中漩绵,變量author和函數(shù)printName都只擁有局部變量
  • 作用域鏈~在JavaScript中,函數(shù)也是對象肛炮,實(shí)際上止吐,JavaScript里一切都是對象。函數(shù)對象和其它對象一樣侨糟,擁有可以通過代碼訪問的屬性和一系列僅供JavaScript引擎訪問的內(nèi)部屬性碍扔。其中一個(gè)內(nèi)部屬性是[[Scope]],由ECMA-262標(biāo)準(zhǔn)第三版定義秕重,該內(nèi)部屬性包含了函數(shù)被創(chuàng)建的作用域中對象的集合不同,這個(gè)集合被稱為函數(shù)的作用域鏈,它決定了哪些數(shù)據(jù)能被函數(shù)訪問(如果變量在該作用域中沒有,則它會逐級向上尋找二拐,直至最頂層)
  • 以上內(nèi)容引用自JavaScript 開發(fā)進(jìn)階:理解 JavaScript 作用域和作用域鏈

代碼部分

一服鹅、以下代碼輸出什么?

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
sex:男
["hunger",28,"男"]
name valley

//getInfo("hunger",28);輸出結(jié)果為
name:hunger
age:28
sex:undefined
["hunger",28]
name valley

//getInfo("男");輸出結(jié)果為
name:男
age:undefined
sex:undefined
["男"]
name valley

在chrome上運(yùn)行如下圖所示


代碼1運(yùn)行效果圖

二卓鹿、寫一個(gè)函數(shù)菱魔,返回參數(shù)的平方和?

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

在chrome中一下效果圖


代碼2運(yùn)行效果圖

三吟孙、如下代碼的輸出澜倦?為什么?

console.log(a);//輸出結(jié)果為undefined
var a = 1;//輸出結(jié)果為1
console.log(b);// Uncaught ReferenceError: b is not defined

造成以上結(jié)果的原因是變量提升杰妓,即JS引擎在解析代碼時(shí)會把所有的變量聲明提到代碼頭部藻治,再一行一行的執(zhí)行代碼,所以第一行代碼輸出結(jié)果為undefined巷挥;而第三行代碼是因?yàn)閎并不是變量桩卵,所以會報(bào)錯(cuò);以上代碼相當(dāng)于以下過程

var a;//變量聲明提升
console.log(a);
a = 1;
console.log(b);

四倍宾、如下代碼的輸出雏节?為什么?

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

以上代碼的輸出結(jié)果為

//sayName("world");輸出結(jié)果為hello world
//sayAge(10);輸出結(jié)果為Uncaught TypeError: sayAge is not a function

第一行代碼由于函數(shù)聲明提升高职,整個(gè)sayName函數(shù)提到代碼頭部钩乍,則在執(zhí)行sayName("world")時(shí)輸出正常結(jié)果;第二行代碼由于sayAge是函數(shù)表達(dá)式怔锌,則js引擎在解析代碼時(shí)寥粹,只是把var sayAge提到代碼頭部,并未把整個(gè)函數(shù)部分提到代碼頭部埃元,所以在執(zhí)行時(shí)會報(bào)錯(cuò)涝涤,以上內(nèi)容相當(dāng)于以下過程

function sayName(name){
    console.log('hello ', name);
}//函數(shù)聲明前置將整個(gè)函數(shù)提到代碼頭部
var sayAge;//函數(shù)表達(dá)式只是把var sayAge提到代碼頭部
sayName('world');//輸出結(jié)果為hello world
sayAge(10);//sayAge并不是一個(gè)函數(shù),則會報(bào)錯(cuò)
sayAge = function(age){
    console.log(age);
};//將右邊的函數(shù)賦值給sayAge

五岛杀、如下代碼的輸出阔拳?為什么?

function fn(){}
var fn = 3;
console.log(fn);//輸出結(jié)果為3

由于變量聲明前置和函數(shù)聲明前置类嗤,以上代碼相當(dāng)于一下過程

var fn;//變量聲明前置衫生,將var fn提到代碼頭部
function fn(){}//函數(shù)聲明前置
fn = 3;//將數(shù)值3賦值給fn
console.log(fn);//最終輸出結(jié)果為3

六、如下代碼的輸出土浸?為什么?

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

最終出現(xiàn)的結(jié)果是

//fn(10);輸出結(jié)果為
function fn2(){
        console.log('fnnn2');
    }
3
function fn(fn2){
   console.log(fn2);
   var fn2 = 3;
   console.log(fn2);
   console.log(fn);
   function fn2(){
        console.log('fnnn2');
    }
 }

出現(xiàn)以上結(jié)果相當(dāng)于js引擎在解析代碼時(shí)做了以下事情

function fn(fn2){
    var fn2;//變量聲明提升
    function fn2(){
         console.log('fnnn2');
     }//函數(shù)聲明提升
    console.log(fn2);//輸出結(jié)果為fn2函數(shù)
    fn = 3;//fn被重新賦值
    console.log(fn2);//輸出結(jié)果為3
    console.log(fn);//輸出結(jié)果為fn函數(shù)
 }
fn(10);

七、如下代碼的輸出彭羹?為什么黄伊?

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

以上代碼輸出結(jié)果為

//console.log(fn(fn));
Uncaught TypeError: fn is not a function

出現(xiàn)以上結(jié)果是因?yàn)镴S引擎在解析代碼時(shí)做了以下事情

var fn;//變量聲明提升
function fn(fn){
     console.log(fn);
}//函數(shù)聲明提升
fn = 1;//把數(shù)值1賦值給函數(shù)fn
console.log(fn(fn));//會報(bào)錯(cuò),因?yàn)閒n不是函數(shù)派殷,已經(jīng)被賦值為1

八还最、如下代碼的輸出墓阀?為什么?

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

最終輸出結(jié)果為

console.log(i);//輸出結(jié)果為10
console.log(j);//輸出結(jié)果為100

相當(dāng)于以下過程

var i;//變量提升拓轻,將var i提到代碼頭部
var j;//變量提升斯撮,將var j也提到代碼頭部
console.log(i);//undefined,此時(shí)變量i還未賦值
console.log(j);//undefined扶叉,此時(shí)變量j也還未賦值
for(var i=0;i<10;i++){
     var j = 100;
}
console.log(i);//在for循環(huán)里執(zhí)行完后勿锅,i為10
console.log(j)//在for循環(huán)執(zhí)行后,j被賦值為100

九枣氧、如下代碼的輸出溢十?為什么 ?

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

最終輸出結(jié)果為

undefined
100
10

相當(dāng)于以下過程

var i;//變量提升达吞,將var i提到代碼頭部
var fn;//變量提升张弛,將var i提到代碼頭部
function fn(){
    var i;//函數(shù)體內(nèi)部的變量提升
    function fn2(){
        i = 100;
    }//函數(shù)體內(nèi)部的函數(shù)聲明提升
    console.log(i);//undefined,因?yàn)榇藭r(shí)的i只是聲明酪劫,但是還未賦值
    i = 99;//把99賦值給變量i
    fn2();//執(zhí)行fn2函數(shù)吞鸭,執(zhí)行完后結(jié)果是i的值為100
    console.log(i);//100
}//函數(shù)聲明提升,將整個(gè)函數(shù)提到代碼頭部
fn();//執(zhí)行函數(shù)fn覆糟,執(zhí)行完后刻剥,得到undefined和100l兩個(gè)結(jié)果
i = 10;//把10賦值給ifn = 20;//把20賦值給fn
console.log(i);//10

十、如下代碼的輸出搪桂?為什么透敌?

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

最終輸出結(jié)果如下圖


代碼10運(yùn)行效果圖
  • 首先,立即執(zhí)行函數(shù)時(shí)沒有函數(shù)聲明前置的踢械,則以上代碼會按照順序來執(zhí)行酗电,解釋如下
var say = 0;//把0賦值給變量say
(function say(n){
    console.log(n);//輸出給定的參數(shù)n~10,9,8,7,6,5,4,3,2
    if(n<3) return;//當(dāng)n<3時(shí),跳出函數(shù)内列,故當(dāng)n為2時(shí)跳出函數(shù)
    say(n-1);
}( 10 ));
console.log(say);//輸出為0撵术,因?yàn)榱⒓磮?zhí)行函數(shù)執(zhí)行完了就完了,這里是變量say

版權(quán)聲明:本教程版權(quán)歸鄧攀和饑人谷所有话瞧,轉(zhuǎn)載須說明來源D塾搿!=慌拧划滋!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市埃篓,隨后出現(xiàn)的幾起案子处坪,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,430評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件同窘,死亡現(xiàn)場離奇詭異玄帕,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)想邦,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評論 3 398
  • 文/潘曉璐 我一進(jìn)店門裤纹,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人丧没,你說我怎么就攤上這事鹰椒。” “怎么了骂铁?”我有些...
    開封第一講書人閱讀 167,834評論 0 360
  • 文/不壞的土叔 我叫張陵吹零,是天一觀的道長。 經(jīng)常有香客問我拉庵,道長灿椅,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,543評論 1 296
  • 正文 為了忘掉前任钞支,我火速辦了婚禮茫蛹,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘烁挟。我一直安慰自己婴洼,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,547評論 6 397
  • 文/花漫 我一把揭開白布撼嗓。 她就那樣靜靜地躺著柬采,像睡著了一般。 火紅的嫁衣襯著肌膚如雪且警。 梳的紋絲不亂的頭發(fā)上粉捻,一...
    開封第一講書人閱讀 52,196評論 1 308
  • 那天,我揣著相機(jī)與錄音斑芜,去河邊找鬼肩刃。 笑死,一個(gè)胖子當(dāng)著我的面吹牛杏头,可吹牛的內(nèi)容都是我干的盈包。 我是一名探鬼主播,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼醇王,長吁一口氣:“原來是場噩夢啊……” “哼呢燥!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起寓娩,我...
    開封第一講書人閱讀 39,671評論 0 276
  • 序言:老撾萬榮一對情侶失蹤疮茄,失蹤者是張志新(化名)和其女友劉穎滥朱,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體力试,經(jīng)...
    沈念sama閱讀 46,221評論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,303評論 3 340
  • 正文 我和宋清朗相戀三年排嫌,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了畸裳。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,444評論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡淳地,死狀恐怖怖糊,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情颇象,我是刑警寧澤伍伤,帶...
    沈念sama閱讀 36,134評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站遣钳,受9級特大地震影響扰魂,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜蕴茴,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,810評論 3 333
  • 文/蒙蒙 一劝评、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧倦淀,春花似錦蒋畜、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至愿棋,卻和暖如春科展,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背初斑。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評論 1 272
  • 我被黑心中介騙來泰國打工辛润, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人见秤。 一個(gè)月前我還...
    沈念sama閱讀 48,837評論 3 376
  • 正文 我出身青樓砂竖,卻偏偏與公主長得像,于是被迫代替她去往敵國和親鹃答。 傳聞我的和親對象是個(gè)殘疾皇子乎澄,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,455評論 2 359

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

  • 函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別 (*)解析器會率先讀取函數(shù)聲明,并使其在執(zhí)行任何代碼之前可以訪問测摔;函數(shù)表達(dá)式則必須...
    coolheadedY閱讀 390評論 0 1
  • 工廠模式類似于現(xiàn)實(shí)生活中的工廠可以產(chǎn)生大量相似的商品置济,去做同樣的事情解恰,實(shí)現(xiàn)同樣的效果;這時(shí)候需要使用工廠模式。簡單...
    舟漁行舟閱讀 7,777評論 2 17
  • 1.函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別 (*) 區(qū)別: 函數(shù)聲明后面的分號可加可不加浙于,不加也不影響接下來語句的執(zhí)行护盈,但...
    Sheldon_Yee閱讀 401評論 0 1
  • 一、函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別羞酗?(*) ECMAScript里面規(guī)定了三種聲明函數(shù)的方式: 構(gòu)造函數(shù)函數(shù)也是對...
    婷樓沐熙閱讀 466評論 0 2
  • Define: .new promise傳入的函數(shù)里面是立即執(zhí)行的 . promise 是一個(gè)對象腐宋,里面有三個(gè)狀態(tài)...
    享悅moonlight閱讀 358評論 0 0