函數(shù)

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

//函數(shù)聲明

function wscat(type){
   return type="wscat";
}

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

var oaoafly =function (type){
  return type="oaoafly";
}

區(qū)別

  1. 函數(shù)聲明不管在哪里定義访圃,該函數(shù)都可以進(jìn)行調(diào)用。而函數(shù)表達(dá)式的值必須是在函數(shù)表達(dá)式賦值完成后秧倾,該函數(shù)才能調(diào)用馁龟。
  2. 對于函數(shù)聲明崩侠,js解析器會(huì)優(yōu)先讀取,確保在所有 代碼執(zhí)行前聲明已經(jīng)被解析坷檩。而函數(shù)表達(dá)式却音,如同其他基本類型的變量一樣,只在執(zhí)行到某一句的時(shí)候也會(huì)對其進(jìn)行解析淌喻。

聲明前置

變量聲明前置

變量聲明前置就是在一個(gè)作用域塊中僧家,所有的變量都被放在塊的開始聲明。

var a=1;
function main(){
  console.log(a);
  var a=2;
}

main()//輸出undefined;
為什么會(huì)輸出undefined呢裸删?是因?yàn)槟_本在運(yùn)行的時(shí)候會(huì)自動(dòng)將變量聲明前置解析如下:

var a=1;
function main(){
  var a;
  console.log(a);
  a=2;
}//所以八拱,我們在寫js的時(shí)候應(yīng)該盡量將變量聲明放在作用域的開始地方。

函數(shù)聲明前置

使用function關(guān)鍵字就可以聲明一個(gè)函數(shù),它的特征是函數(shù)聲明提升肌稻,執(zhí)行代碼前會(huì)先讀取函數(shù)聲明拱烁,即函數(shù)聲明不必放在調(diào)用的前面夕玩。

var a=3;
console.log(a);
sayHello();
function sayHello (){
  console.log("hello");
}
解析為
var a;
function sayHello(){}
然后:conslole.log(a);
         a=3;
        sayHello();

對于函數(shù)表達(dá)式,和var一個(gè)變量沒什么區(qū)別。

arguments

可以在函數(shù)體內(nèi)讀取所有的參數(shù)酵熙,這就是argunments對象的由來凌彬。

arguments對象的使用

  • 通過方括號(hào)語法訪問每一個(gè)元素
var fun=function(one){
  console.log(arguments[0]);
  console.log(arguments[1]);
  console.log(arguments[2]);
}
fun(1,2,3)
//1
//2
//3
  • 通過length屬性变屁,查看到底要幾個(gè)參數(shù)
function fun(){
  return argunments.length;
}
fun(1,2,3,)
  • 參數(shù)賦值(嚴(yán)格模式下不容許)
var fun=function (a,b){
  argunments[1]=2;
  return a+b;
}
fun(1,1)//3

重載

js沒有重載议惰,但是可以在js中實(shí)現(xiàn)重載的功能,即傳遞不同的實(shí)參腹泌,可以自動(dòng)調(diào)用匹配嘶卧。

function print(name,age,sex){
  if(name){
    console.log(name);
}
  if(age){
  console.log(age);
}
  if(sex){
  console.log(sex);
}
}
print("byyu",26)

立即執(zhí)行函數(shù)

最常用的兩種寫法:

(function (){/*code*/}());
(function (){/*code*/})();

為什么第一種執(zhí)行而不報(bào)錯(cuò)呢?因?yàn)樵趈s里,括號(hào)內(nèi)部不能包含語句凉袱,當(dāng)解析器對代碼進(jìn)行解析的時(shí)候芥吟,先碰到了(),然后碰到function關(guān)鍵字就會(huì)自動(dòng)將()里面的代碼識(shí)別為函數(shù)表達(dá)式而不是函數(shù)聲明专甩。

作用

模擬塊作用域
js只有函數(shù)作用域钟鸵,在同時(shí)調(diào)用多個(gè)庫的情況下,很容易造成對象或者變量的覆蓋涤躲。
liba.js

var num=1;

libb.js

var num=2;

如果在頁面上同時(shí)引用liba,js和liba,js兩個(gè)庫棺耍。必然導(dǎo)致num的覆蓋,為此:
liba.js

(function(){
  var num=1;
})();
libb,js
(function(){
  var num=2;
})();

經(jīng)過改造之后种樱,兩個(gè)庫的代碼就完全獨(dú)立烈掠,互不影響了。

用遞歸實(shí)現(xiàn) n缸托!

function factor(n){
  if (n==1){
  return 1
}
  return n*factor(n-1);
}
factor(100)

代碼輸出

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('饑人谷', 2, '男');//name:饑人谷,age:2瘾蛋,sex:男俐镐,['饑人谷',2哺哼,'男']佩抹,name:valley
getInfo('小谷', 3);//name:小谷,age:3取董,undefined,['小谷棍苹,'3'],name:valley;
getInfo('男');name:男茵汰,undefined,undefined,['男']枢里,name:valley;

寫一個(gè)函數(shù),返回參數(shù)的平方和

function sumOfSquares(){
  var result=0;
  for(i=0;i<arguments.length;i++){
  result=result+argument[i]+argument[i];
}
  return result;
}
var demo=sumOfSquares(1,3,4);
console.log(demo);

代碼輸出(變量提升)

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

console.log(a)輸出undefined;因?yàn)閍變量提升,相當(dāng)于

var a;
console.log(a);

只聲明了沒有賦值栏豺,為undefined彬碱。
console.log(b)會(huì)報(bào)錯(cuò),因?yàn)榧葲]有聲明也沒有賦值奥洼。

代碼輸出(函數(shù)聲明前置)

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

sayName函數(shù)會(huì)輸出'hello''world',sayAge會(huì)報(bào)錯(cuò)
原因:第一個(gè)是函數(shù)聲明巷疼,會(huì)函數(shù)聲明前置,所以函數(shù)聲明不必放在調(diào)用的前面灵奖。而第二個(gè)是函數(shù)表達(dá)式嚼沿,相當(dāng)于普通變量,所以函數(shù)調(diào)用必須放在函數(shù)聲明的后面瓷患,否則會(huì)報(bào)錯(cuò)骡尽。

作用域鏈(查找過程偽代碼)

var x = 10
bar() 
function foo() {
  console.log(x)
}
function bar(){
  var x = 30
  foo()
}//輸出10

原因:

globalcontext={
Ao{  x:10;
  foo:function;
  bar:function;}
scope:null;
}}
foo.[[scope]]=globalcontext.Ao;
bar.[[scope]]=globalcontext.Ao;
barcontext={
  Ao{
  x:30;}
  scope:globalcontext.Ao;
}
foocontext={
  Ao{};
  scope:globalcontext.Ao;
}//調(diào)用foo時(shí)候會(huì)先從Ao里面找,Ao里面為空尉尾,會(huì)向globalcontext.Ao里面找爆阶,找到x=10,所以會(huì)打印出10。

作用域鏈(查找過程偽代碼)

var x = 10;
bar()
function bar(){
var x = 30;
function foo(){
console.log(x)
}
foo();
}
過程:

1. globalcontext={
   Ao:{
    x:10;
    bar: function;
}
  scope:null;
}   
bar.[[scope]]=globalcontext.Ao;
2. barcontext={
  Ao:{
    x:30;
    foo:function;
}
  scope:bar.[[scope]]=globalcontext.Ao;
}
foo.[[scope]]=barcontext.Ao;
3. foocontext={
  Ao:{};
  scope:foo.[[scope]]=barcontext.Ao;
}//輸出30.調(diào)用foo()的時(shí)候沙咏,會(huì)在foo的Ao中查找辨图,可見里面沒有。所以會(huì)在scope里面找肢藐,barcontext.Ao里面有x=30;所以輸出的結(jié)果為30故河。

查找過程的偽代碼(立即執(zhí)行函數(shù))

var x = 10;
bar() 
function bar(){
  var x = 30;
  (function (){
    console.log(x)
  })()//等價(jià)于function foo(){console.log(x);}
}

過程:

1. globalcontext={  
  Ao:{
  x:10;
  bar:function;
}
scope:null;
}
bar.[[scope]]=globalcontext.Ao;
2. barcontext={
  Ao:{
    x:30;
    foo:function;
}
scope:globalcontext.Ao;
}
foocontext.[[scope]]=barcontext.Ao;
3. foocontext={
    Ao:{};
    scope:barcontext.Ao;
}//調(diào)用foo()函數(shù)時(shí),Ao中沒有值吆豹。所以在scope:barcontext.Ao查找;其中中x=30,所以輸出30

作用域鏈(查找過程偽代碼)

var a = 1;

function fn(){
  console.log(a)//輸出undefined;因?yàn)樽兞柯暶髑爸胿ar a
  var a = 5
  console.log(a)輸出5鱼的,因?yàn)閍=5
  a++
  var a
  fn3()
  fn2()
  console.log(a)//輸出6,因?yàn)閍++,a為6

  function fn2(){
    console.log(a)//輸出20痘煤,因?yàn)閒n2.[[scope]]=fncontext.Ao;并且a=20,將
                             fncontext.Ao中的a=6改為20凑阶;
    a = 20
  }
}

function fn3(){
  console.log(a)//輸出200,因?yàn)閒n3中的AO為空衷快,所以會(huì)在
                      globalcontext.Ao;中找宙橱,又因?yàn)閍=200,將a=1改為200,所以a=200
  a = 200
}

fn()
console.log(a)

過程:

globalcontext={
  Ao:{
    a:1;
    fn3:function;
    fn:function;
}
scope:null;
}
fn3.[[scope]]=globalcontext.Ao;
fn.[[scope]]=globalcontext.Ao;
fncontext={
  Ao:{
    a:6;
    fn2:function;
  scope:globalcontext.Ao;
}
fn2.[[scope]]=fncontext.Ao;
}
fn3context={
    Ao:{};
    scope:globalcontext.Ao;
}
fn2context={
  Ao:{};
  scope:fncontext.Ao;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末蘸拔,一起剝皮案震驚了整個(gè)濱河市师郑,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌调窍,老刑警劉巖宝冕,帶你破解...
    沈念sama閱讀 218,036評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異邓萨,居然都是意外死亡地梨,警方通過查閱死者的電腦和手機(jī)菊卷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,046評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來湿刽,“玉大人的烁,你說我怎么就攤上這事≌┕耄” “怎么了渴庆?”我有些...
    開封第一講書人閱讀 164,411評論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長雅镊。 經(jīng)常有香客問我襟雷,道長,這世上最難降的妖魔是什么仁烹? 我笑而不...
    開封第一講書人閱讀 58,622評論 1 293
  • 正文 為了忘掉前任耸弄,我火速辦了婚禮,結(jié)果婚禮上卓缰,老公的妹妹穿的比我還像新娘计呈。我一直安慰自己,他們只是感情好征唬,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,661評論 6 392
  • 文/花漫 我一把揭開白布捌显。 她就那樣靜靜地躺著,像睡著了一般总寒。 火紅的嫁衣襯著肌膚如雪扶歪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,521評論 1 304
  • 那天摄闸,我揣著相機(jī)與錄音善镰,去河邊找鬼。 笑死年枕,一個(gè)胖子當(dāng)著我的面吹牛炫欺,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播熏兄,決...
    沈念sama閱讀 40,288評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼竣稽,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了霍弹?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,200評論 0 276
  • 序言:老撾萬榮一對情侶失蹤娃弓,失蹤者是張志新(化名)和其女友劉穎典格,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體台丛,經(jīng)...
    沈念sama閱讀 45,644評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡耍缴,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,837評論 3 336
  • 正文 我和宋清朗相戀三年砾肺,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片防嗡。...
    茶點(diǎn)故事閱讀 39,953評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡变汪,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蚁趁,到底是詐尸還是另有隱情裙盾,我是刑警寧澤,帶...
    沈念sama閱讀 35,673評論 5 346
  • 正文 年R本政府宣布他嫡,位于F島的核電站番官,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏钢属。R本人自食惡果不足惜徘熔,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,281評論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望淆党。 院中可真熱鬧酷师,春花似錦、人聲如沸染乌。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,889評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽慕匠。三九已至饱须,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間台谊,已是汗流浹背蓉媳。 一陣腳步聲響...
    開封第一講書人閱讀 33,011評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留锅铅,地道東北人酪呻。 一個(gè)月前我還...
    沈念sama閱讀 48,119評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像盐须,于是被迫代替她去往敵國和親玩荠。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,901評論 2 355

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

  • 一贼邓、函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別阶冈?(*) ECMAScript里面規(guī)定了三種聲明函數(shù)的方式: 構(gòu)造函數(shù)函數(shù)也是對...
    婷樓沐熙閱讀 463評論 0 2
  • 概念 1、函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別塑径? ECMAScript規(guī)定了三種聲明函數(shù)方式: 構(gòu)造函數(shù)首先函數(shù)也是對象...
    周花花啊閱讀 468評論 1 1
  • 問答: 1. 函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別 (*) 在日常的任務(wù)中女坑,JavaScript主要使用下面兩種方式創(chuàng)建...
    小木子2016閱讀 319評論 0 0
  • 問答部分 一、函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別统舀? 二者表示函數(shù)的方式不一樣匆骗,如下 函數(shù)聲明(函數(shù)名稱不可少) 函數(shù)表...
    dengpan閱讀 418評論 0 0
  • 1. 函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別 (*) 函數(shù)在JS中有三種方式來定義:函數(shù)聲明(function decla...
    進(jìn)擊的阿群閱讀 442評論 0 1