JS--函數(shù)

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

函數(shù)聲明:
function functionName(){
  statement;
}// 無分號(hào)

functionName();
函數(shù)表達(dá)式:
var functionName = function(){
  statement;
};// 有分號(hào)

functionName();
  • 以上為兩者寫法的區(qū)別腺毫。由名稱可以看出 “函數(shù)表達(dá)式” 的實(shí)質(zhì)為表達(dá)式肯污,“函數(shù)聲明”則是使用function關(guān)鍵字聲明的一個(gè)函數(shù)掏熬,而它們執(zhí)行和調(diào)用的方法完全相同。

  • 兩者最大區(qū)別在于聲明前置的不同豁辉。如下:
    fn("valley");
    var fn = function (str){
    console.log(str);// Uncaught TypeError: fn is not a function
    }

    var fn = function (str){
      console.log(str);// 輸出結(jié)果 valley
    };
    fn("valley");
    //使用函數(shù)表達(dá)式,聲明前置的規(guī)則和變量一樣把将!(具體參照下一題)
    
    -----------------------------------------------------------------------------
    
    function fn(str){
      console.log(str);// 輸出結(jié)果 valley
    }
    fn("valley");
    //使用函數(shù)聲明的方式没酣,那么即使函數(shù)寫在最后也可以在前面語句調(diào)用,當(dāng)然前提是函數(shù)聲明部分已經(jīng)被下載到本地
    

注:推薦使用函數(shù)聲明被饿,不用表達(dá)式四康。ps:何必自造麻煩~(函數(shù)調(diào)用要有分號(hào)哦)

函數(shù)聲明VS函數(shù)表達(dá)式

什么是變量的聲明前置?什么是函數(shù)的聲明前置

聲明前置是把該聲明的變量和函數(shù)提升到自身所在作用域的頂部狭握。

  • 變量的聲明前置

先獲取所有被聲明的變量(僅變量名闪金,不包括其值),然后再逐行運(yùn)行论颅。這使得所有
變量的聲明被提前到作用域頂部哎垦,賦值保留在原地;而“函數(shù)表達(dá)式的聲明相當(dāng)于變量的聲明”恃疯,當(dāng)函數(shù)作為值賦給變量時(shí)只有變量“被提前”了(var functionName; 提前了)漏设,函數(shù)體并沒有“被提前”。

  console.log(a);// undefined,未賦值
  var a = 1;
  console.log(a);// 1今妄,為變量a賦值等于1
  console.log(b);// error,報(bào)錯(cuò)郑口。不存在
  //以上代碼相當(dāng)于以下:
  var a;
  console.log(a);
  a = 1;
  console.log(a);
  console.log(b);
  • 函數(shù)的聲明前置

函數(shù)的聲明“整個(gè)”被提前,使函數(shù)在執(zhí)行任何代碼之前都可以訪問盾鳞。

  a(1);// 有分號(hào)犬性,函數(shù)調(diào)用形式
  function a(name){// name為占位符,形參
    console.log(name);// 輸出結(jié)果 1
  }
  以上代碼相當(dāng)于以下:
  function a(name){
    console.log(name);// 輸出結(jié)果 1
  }
  a(1);

特別注意腾仅,若有同一名稱的變量和函數(shù)乒裆,則函數(shù)會(huì)覆蓋變量。

console.log(a);
function a(){ return;}// 控制臺(tái)a顯示為函數(shù)推励,證明聲明前置時(shí)鹤耍,函數(shù)會(huì)覆蓋同名的變量聲明。
var a;

參考文章

arguments 是什么

簡(jiǎn)單說就是验辞,收集了函數(shù)中參數(shù)的一個(gè)類數(shù)組對(duì)象稿黄。
arguments可以打印出你所傳入的所有參數(shù)且以酷似數(shù)組的形式出現(xiàn)。

function sum(){ 
  var sum = 0; 
  for(var i = 0; i < arguments.length; i++){ 
    sum = sum + arguments[i];
  }
}// 函數(shù)內(nèi)部,你可以使用arguments對(duì)象獲取到該函數(shù)的所有傳入?yún)?shù)
arguments作用:

可實(shí)現(xiàn)JS的類似函數(shù)重載的功能受神。

函數(shù)的重載怎樣實(shí)現(xiàn)抛猖?

重載是很多面向?qū)ο笳Z言實(shí)現(xiàn)多態(tài)的手段之一,在靜態(tài)語言中確定一個(gè)函數(shù)的手段是靠方法簽名——函數(shù)名+參數(shù)列表鼻听,也就是說相同名字的函數(shù)參數(shù)個(gè)數(shù)不同或者順序不同都被認(rèn)為是不同的函數(shù)财著,稱為函數(shù)重載。

在JavaScript中沒有函數(shù)重載的概念撑碴,函數(shù)通過名字確定唯一性撑教,參數(shù)不同也被認(rèn)為是相同的函數(shù),后面的覆蓋前面的醉拓。

  function sum(){ 
    console.log(arguments);
  }
  sum(1);
  sum(1, 2, 3);/* js中的函數(shù)無傳統(tǒng)意義的重載 */


  function sum(a, b){ 
    return a + b;
  }
  function sum(a, b, c){ 
    return a + b + c;
  }
  sum(1, 2);//出錯(cuò)
  sum(1, 2, 3);/* 用arguemnts實(shí)現(xiàn)重載*/


  function newSum(){ 
    var sum = 0; 
    for(var i = 0; i< arguments.length; i++){ 
      sum += arguments[i];
    } 
    return sum;
  }

立即執(zhí)行函數(shù)表達(dá)式是什么伟姐?有什么作用

立即調(diào)用函數(shù)表達(dá)式常見的有兩種寫法:

(function(){} ());

(function(){})();

立即調(diào)用函數(shù)表達(dá)式作用:

立即執(zhí)行函數(shù)可以將寫在函數(shù)體內(nèi)的語句直接執(zhí)行收苏。區(qū)別于普通語句,立即執(zhí)行函數(shù)內(nèi)的變量不會(huì)干擾函數(shù)體外愤兵,形成一個(gè)類似區(qū)塊的空間鹿霸。它能做到各模塊的低耦合,減少對(duì)全局作用域的污染秆乳,省去起函數(shù)名懦鼠。

知乎-立即調(diào)用的函數(shù)表達(dá)式
cnblogs-深入理解JavaScript系列

什么是函數(shù)的作用域鏈

在JavaScript中,函數(shù)也是對(duì)象屹堰,實(shí)際上肛冶,JavaScript里一切都是對(duì)象。函數(shù)對(duì)象和其它對(duì)象一樣扯键,擁有可以通過代碼訪問的屬性和一系列僅供JavaScript引擎訪問的內(nèi)部屬性睦袖。其中一個(gè)內(nèi)部屬性是[[Scope]],由ECMA-262標(biāo)準(zhǔn)第三版定義荣刑,該內(nèi)部屬性包含了函數(shù)被創(chuàng)建的作用域中對(duì)象的集合馅笙,這個(gè)集合被稱為函數(shù)的作用域鏈,它決定了哪些數(shù)據(jù)能被函數(shù)訪問厉亏。
JavaScript 開發(fā)進(jìn)階:理解 JavaScript 作用域和作用域鏈

代碼練習(xí)

1.以下代碼輸出什么延蟹? (難度2)
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é)果:

后臺(tái)調(diào)試結(jié)果
2.寫一個(gè)函數(shù),返回參數(shù)的平方和叶堆?如 (難度2)
function sumOfSquares(){ 
} 
sumOfSquares(2,3,4);// 29 
sumOfSquares(1,3);// 10
函數(shù)示例
3.如下代碼的輸出?為什么 (難度1)
console.log(a); 
var a = 1;// undefined 
console.log(b);// "error"
結(jié)果
代碼結(jié)果
原因

以上代碼還可以寫成如下:

var a;// 變量聲明前置
console.log(a);// 變量a已被聲明斥杜,但還未被解析到賦值部分虱颗,所以u(píng)ndefined
a = 1;
console.log(b)// 變量b未被聲明,故解析報(bào)錯(cuò)"error"

4.如下代碼的輸出蔗喂?為什么 (難度1)

sayName('world'); 
sayAge(10); 
function sayName(name){ 
      console.log('hello ', name); 
} 
var sayAge = function(age){ 
      console.log(age); 
};
結(jié)果
后臺(tái)結(jié)果
原因

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

function sayName(name){ 
     console.log('hello ', name); 
}// “函數(shù)聲明格式”的函數(shù)忘渔,“整個(gè)”被提前
var sayAge;// “函數(shù)表達(dá)式格式”的函數(shù),只有“變量”(var functionName;)被提前了缰儿,函數(shù)體并沒有“被提前”
sayName('world');// 調(diào)用畦粮,函數(shù)體正常計(jì)算出結(jié)果
sayAge(10);// 調(diào)用,該“變量”非函數(shù)乖阵,出錯(cuò) 
var sayAge = function(age){ 
  console.log(age); 
};

5.如下代碼的輸出宣赔?為什么 (難度2)

function fn(){
} 
var fn = 3;
console.log(fn);// 結(jié)果為3
分步解析:
  • 步驟1
     var fn;// 變量聲明前置
    //function fn(){
    //}
    //fn = 3;
    console.log(fn);
    
步驟1調(diào)試結(jié)果
  • 步驟2
    var fn;
    function fn(){
    }//fn被聲明成函數(shù)格式,但未賦值 
    //fn = 3;
    console.log(fn);// 
    
步驟2調(diào)試結(jié)果
  • 步驟3
    var fn;
    function fn(){
    } 
    fn = 3;//被賦值瞪浸,同時(shí)重新變?yōu)樽兞扛袷?console.log(fn);
    
步驟3調(diào)試結(jié)果
綜上
var fn;// 變量聲明前置
function fn(){
}// fn被聲明成函數(shù)格式儒将,但未賦值 
fn = 3;//被賦值,同時(shí)重新變?yōu)樽兞扛袷?console.log(fn);//3

6.如下代碼的輸出对蒲?為什么 (難度3)

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

fn(10);
調(diào)試結(jié)果
可看作如下
function fn(fn2){
  var fn2;
  function fn2(){
    console.log('fnnn2');
  }
  console.log(fn2);
  fn2 = 3;
  console.log(fn2);
  console.log(fn);
}

fn(10);
結(jié)果

7.如下代碼的輸出钩蚊?為什么 (難度3)

var fn = 1; 
function fn(fn){ 
  console.log(fn); 
} 
console.log(fn(fn)); //Uncaught TypeError: fn is not a function 
可將JS的解析順序視為
var fn;
function fn(fn){
  console.log(fn);//error
}
fn = 1;
console.log(fn(fn));//所以error

8.如下代碼的輸出贡翘?為什么 (難度**)

//作用域 
console.log(j);//undefined 
console.log(i);//undefined 
for(var i=0; i<10; i++){ 
  var j = 100; 
} 
console.log(i);//10 
console.log(j);//100
可將JS的解析順序視為
var i;
var j;//變量聲明前置
console.log(j);
console.log(i);
for( i=0; i<10; i++){ 
  j = 100; 
}//for語句非函數(shù),不存在函數(shù)作用域砰逻,相當(dāng)于直接定義的變量(具體看下面的解析)
console.log(i);
console.log(j);
調(diào)試解析

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; 
  } 
}
可將JS的解析順序視為
var i;
var fn;
function fn(){
  var i;
  function fn2(){
      i = 100;
  } 
    console.log(i);// undefined
    i = 99;
    fn2();//調(diào)用fn2,作用相當(dāng)于:i = 100;
    console.log(i);//100  
}
fn();//即結(jié)果為:undefined,100
i =10;
fn = 20;
console.log(i);//結(jié)果為:10

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

代碼及結(jié)果
var say; 
(function say(n){ 
console.log(n); 
if(n<3) return; 
say(n-1); }( 10 ));//立即執(zhí)行函數(shù)表達(dá)式得到10-2的遞減   
say = 0;//say變量被賦值0并輸出 
console.log(say);

本教程版權(quán)歸屬于 fin 及 饑人谷 所有蝠咆,轉(zhuǎn)載請(qǐng)說明來源~

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末踊东,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子勺美,更是在濱河造成了極大的恐慌递胧,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件赡茸,死亡現(xiàn)場(chǎng)離奇詭異缎脾,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)占卧,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門遗菠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人华蜒,你說我怎么就攤上這事辙纬。” “怎么了叭喜?”我有些...
    開封第一講書人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵贺拣,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我捂蕴,道長(zhǎng)譬涡,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任啥辨,我火速辦了婚禮涡匀,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘溉知。我一直安慰自己陨瘩,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開白布级乍。 她就那樣靜靜地躺著舌劳,像睡著了一般。 火紅的嫁衣襯著肌膚如雪卡者。 梳的紋絲不亂的頭發(fā)上蒿囤,一...
    開封第一講書人閱讀 51,631評(píng)論 1 305
  • 那天,我揣著相機(jī)與錄音崇决,去河邊找鬼材诽。 笑死底挫,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的脸侥。 我是一名探鬼主播建邓,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼睁枕!你這毒婦竟也來了官边?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤外遇,失蹤者是張志新(化名)和其女友劉穎注簿,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體跳仿,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡诡渴,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了菲语。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片妄辩。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖山上,靈堂內(nèi)的尸體忽然破棺而出眼耀,到底是詐尸還是另有隱情,我是刑警寧澤佩憾,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布哮伟,位于F島的核電站,受9級(jí)特大地震影響妄帘,放射性物質(zhì)發(fā)生泄漏澈吨。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一寄摆、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧修赞,春花似錦婶恼、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至割择,卻和暖如春眷篇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背荔泳。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工蕉饼, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留虐杯,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓昧港,卻偏偏與公主長(zhǎng)得像擎椰,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子创肥,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

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

  • 函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別 (*)解析器會(huì)率先讀取函數(shù)聲明达舒,并使其在執(zhí)行任何代碼之前可以訪問;函數(shù)表達(dá)式則必須...
    coolheadedY閱讀 388評(píng)論 0 1
  • 1. 函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別 (*) 函數(shù)在JS中有三種方式來定義:函數(shù)聲明(function decla...
    進(jìn)擊的阿群閱讀 442評(píng)論 0 1
  • 一叹侄、問答1巩搏、函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別 ()函數(shù)聲明和函數(shù)表達(dá)式都是聲明函數(shù)的方法。函數(shù)聲明:function...
    崔敏嫣閱讀 350評(píng)論 0 0
  • 函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別趾代? 函數(shù)聲明和函數(shù)表達(dá)式是EMACScript規(guī)定的兩種不同的聲明函數(shù)的方法贯底。1.函...
    LeeoZz閱讀 350評(píng)論 0 1
  • 【專題:心聲文筆】 路過一個(gè)路口 簡(jiǎn)單的游戲 幾個(gè)孩童在玩 干凈單純悅耳的笑聲不斷 只是聽到, 便已能想像到他們笑...
    南陽雅月閱讀 221評(píng)論 0 0