JS函數與作用域

函數聲明和函數表達式有什么區(qū)別?

函數聲明和函數表達式是EMACScript規(guī)定的兩種不同的聲明函數的方法刀疙。
1.函數聲明

//聲明函數
function name() { //function+函數名+(參數)+{函數體} 
 console.log ('Jack')
}
//函數調用
  name()

函數聲明會在JavaScript代碼開始時提到最前面進行定義舶赔,因此函數聲明不必在調用之前定義。

2.函數表達式

var name = function () { 
   console.log ('Jack')
}

雖然變量聲明會提到JavaScript代碼開始前谦秧,但是賦值要運行到該行代碼才執(zhí)行竟纳,因此在調用用函數表達式聲明的函數時,聲明必須放到調用前疚鲤。

總結區(qū)別:
1.函數聲明會在代碼開始前定義锥累,函數表達式遇到時才會執(zhí)行。
2.函數聲明必須有函數名集歇,函數表達式則可以省略桶略。

什么是變量的聲明前置?什么是函數的聲明前置诲宇?

  • 變量的聲明前置:

在一個作用域塊中际歼,所有的變量聲明都會被JS引擎放在作用域塊范圍的頂部進行聲明;

  • 函數的聲明前置:

和變量聲明前置一樣姑蓝,執(zhí)行代碼之前會先讀取函數聲明鹅心,只要函數在代碼中進行了聲明,無論它在作用域塊的哪個位置上進行聲明纺荧,JS引擎都會將它的聲明放在作用域塊范圍的頂部進行聲明旭愧;

arguments是什么?

在ECMAScript中,函數的參數在內部是用一個數組來表示的宙暇。在函數體內榕茧,可以用arguments來訪問這個參數數組。arguments是一個類數組對象(不是Array的實例)客给,因為可以使用方括號語法訪問它的每一個元素用押,使用length屬性來確定傳遞進來多少參數,示例:

function test () { 
    console.log (arguments.length); //參數的長度 
    console.log (arguments[0]); //第一個參數                                                   
    console.log (arguments[1]); //第二個參數
}
test ('Jack',1,'888');
//輸出結果為 3靶剑,'Jack'蜻拨,1

JS函數的"重載"怎樣實現?

重載桩引,是函數或者方法有相同的名稱缎讼,但是參數列表不相同的情形,這樣的同名不同參數的函數或者方法之間坑匠,互相稱之為重載函數或者方法血崭。但是在JS,并沒有重載這個概念,但我們可以用另外一種方法實現這個功能:

function test (num) { 
     if (num>=90) { 
        console.log ('優(yōu)秀') 
     } 
     if (num>=60&&num<90) { 
         console.log ('及格') 
      } 
     if (num<60) { 
          console.log ('不及格') 
      }
}
test(95) //輸出 '優(yōu)秀'
test(77) //輸出 '及格'
test(18) //輸出 '不及格'

這樣對于同一個函數夹纫,輸入不同參數就會得到不同結果咽瓷。

立即執(zhí)行函數表達式是什么?有什么作用舰讹?

在JS中我們可以使用函數聲明和函數表達式聲明函數茅姜,再通過函數名進行調用:

function sayName (name) { //函數聲明聲明函數  
  console.log (name);                  
}
sayName ('Jack'); // 調用函數

var sayName = function () { //函數表達式聲明函數     
  console.log (name);
}
sayName ('Jack') // 調用函數

因為在JS中圓括號()內是不能有語句的,括號內容會被當做表達式月匣,因此上面例子可以進行改寫:

(function (name) { 
  console.log (name);
})('Jack')
//或者
(function (name) { 
  console.log (name);
}('Jack')) // 輸出都為Jack

當JS執(zhí)行到該行代碼時钻洒,函數會被定義且立即執(zhí)行,叫做立即執(zhí)行函數表達式锄开。使用立即執(zhí)行函數表達式可以創(chuàng)建一個獨立的作用域素标,形成隔離,避免污染全局萍悴。

求n!头遭,用遞歸來實現

ffunction multiply(n){
    if(n===1){
        return 1;
    }
    return n*multiply(n-1);
}
multiply(3);//6

以下代碼輸出什么?

function getInfo(name, age, sex){ 
    console.log('name:',name); 
    console.log('age:', age); 
    console.log('sex:', sex); 
    console.log(arguments); //輸出整組參數退腥; 
    arguments[0] = 'valley'; //第一個參數賦值為‘valley’
    console.log('name', name); 
}
getInfo('饑人谷', 2, '男'); 
// name:饑人谷任岸,age:2,sex:男狡刘,['饑人谷'享潜,2,'男']嗅蔬,name valley剑按;
getInfo('小谷', 3);
// name:小谷,age:3澜术,sex:undefined艺蝴,['小谷',3]鸟废,name valley猜敢;
getInfo('男');
// name:男,age:undefined盒延,sex:undefined缩擂,['男'],name valley添寺;

寫一個函數胯盯,返回參數的平方和

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

解釋下列代碼的輸出及原因

console.log(a);  // 由于聲明提前,此時a未賦值计露,輸出undefined博脑;
var a = 1;  // a=1;
console.log(b);  //報錯憎乙,b未被聲明;
sayName('world');
sayAge(10);
function sayName(name){ 
  console.log('hello ', name);
}
var sayAge = function(age){ 
  console.log(age);
};
//解釋
function sayName(name){ //函數聲明和變量聲明提前;                      
  console.log('hello ', name);
}
var sayAge;
sayName('world'); //調用函數叉趣,輸出'hello泞边,world';
sayAge(10); //undefined,因為sayAge未定義君账;
sayAge = function(age){ 
  console.log(age);
};
//函數表達式需放到調用前7北ぁ沈善!

如下代碼輸出什么? 寫出作用域鏈查找過程偽代碼

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

/*作用域查找過程
goblecontext = { 
  AO: { 
    X=10
    foo: function 
    bar: function 
  } 
  foo.[[scope]]: goblecontext.AO 
  bar.[[scope]]: goblecontext.AO
}
foocontext = { 
  AO: {} 
  scope: goblecontext.AO
}
barcontext = { 
  AO: { 
    x = 30 
  } 
  scope: goblecontext.AO
}*/
var x = 10;
bar() 
function bar(){
var x = 30;
function foo(){ 
console.log(x) 
}
foo();
} //輸出30
/*作用域查找過程
goblecontext = { 
  AO: { 
    x=10 
    bar:function 
  } 
  bar.[[scopr]]=goblecontext.AO
}
barcontext = { 
  AO: { 
    x=30 
    foo:function 
  } 
  foo.[[scope]]=barcontext.AO 
  scope=goblecontext.AO
}
foocontext = { 
  AO: {} 
  scope=barcontext.AO
}*/
var x = 10;
bar() 
function bar(){
var x = 30;
(function (){ 
  console.log(x)
})()
} //輸出30

/*作用域查找
goblecontext = { 
  AO: { 
    x=10 
    bar:function
  } 
  bar.[[scope]]=goblecontext.AO 
  scope=null
}
barcontext = { 
  AO: { 
    x=30 
    f:function 
  } 
  f.[[scope]]=barcontext.AO 
  scope=goblecontext.AO
}
fcontext = { 
  AO: {} 
  scope=barcontext.AO
}*/
var a = 1;
function fn(){
console.log(a)
var a = 5
console.log(a)
a++
var a
fn3()
fn2()
console.log(a)
function fn2(){ 
  console.log(a) 
  a = 20
}
}
function fn3(){
console.log(a)
a = 200
}
fn() //輸出:undefined,5闻牡,1净赴,6,20罩润,200玖翅;
console.log(a)
/*
goblecontext = {
   AO: { 
     a: undefined 
     fn: function 
     fn3: function 
   } 
   scope = null
   fn.[[scope]] = goblecontext.AO 
   fn3.[[scope]] = goblecontext.AO
}
fncontext = { 
   AO: { 
          a: undefinef 
          fn2: function 
  } 
 scope = goblecontext.AO 
 fn2.[[scope]] = fncontext.AO
}
fn2context = { 
  AO: { 
           a: 20 
  } 
  scope = fncontext.AO
}
fn3context = { 
  AO: { 
    a: 200 
   } 
  scope = goblecontext.AO
}*/
遇到fn(),開始執(zhí)行:
console.log(a),,此時fncontextAO中a未被賦值割以,輸出undefined金度;
a = 5;
console.log(a),此時fncontextAO中a被賦值為5严沥,輸出5猜极;
a++,fncontextAO中a變?yōu)?消玄;
var a跟伏,因為a已經存在,故無意義翩瓜;
fn3()受扳,執(zhí)行fn3(),進入fn3context兔跌;
console.log(a)勘高,goblecontextAO中,a=1坟桅,故輸出1华望;
a=200,goblecontextAO中a變?yōu)?00桦卒;
fn2立美,執(zhí)行fn2(),進入fn2context方灾;
console.log(a)建蹄,fncontextAO中碌更,a=6,故輸出6洞慎;
a=20痛单,fncontextAO中,a變?yōu)?0劲腿;
console.log(a)旭绒,fncontextAO中,a為20焦人,故輸出20挥吵;
fn執(zhí)行完畢;
console.log(a)花椭,goblecontextAO中忽匈,a為200,故輸出200矿辽;
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末丹允,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子袋倔,更是在濱河造成了極大的恐慌雕蔽,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,657評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件宾娜,死亡現場離奇詭異批狐,居然都是意外死亡,警方通過查閱死者的電腦和手機碳默,發(fā)現死者居然都...
    沈念sama閱讀 92,889評論 3 394
  • 文/潘曉璐 我一進店門徐绑,熙熙樓的掌柜王于貴愁眉苦臉地迎上來疯潭,“玉大人盅安,你說我怎么就攤上這事懒棉。” “怎么了该抒?”我有些...
    開封第一講書人閱讀 164,057評論 0 354
  • 文/不壞的土叔 我叫張陵慌洪,是天一觀的道長。 經常有香客問我凑保,道長冈爹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,509評論 1 293
  • 正文 為了忘掉前任欧引,我火速辦了婚禮频伤,結果婚禮上,老公的妹妹穿的比我還像新娘芝此。我一直安慰自己憋肖,他們只是感情好因痛,可當我...
    茶點故事閱讀 67,562評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著岸更,像睡著了一般鸵膏。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上怎炊,一...
    開封第一講書人閱讀 51,443評論 1 302
  • 那天谭企,我揣著相機與錄音,去河邊找鬼评肆。 笑死债查,一個胖子當著我的面吹牛,可吹牛的內容都是我干的糟港。 我是一名探鬼主播攀操,決...
    沈念sama閱讀 40,251評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼院仿,長吁一口氣:“原來是場噩夢啊……” “哼秸抚!你這毒婦竟也來了?” 一聲冷哼從身側響起歹垫,我...
    開封第一講書人閱讀 39,129評論 0 276
  • 序言:老撾萬榮一對情侶失蹤剥汤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后排惨,有當地人在樹林里發(fā)現了一具尸體吭敢,經...
    沈念sama閱讀 45,561評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,779評論 3 335
  • 正文 我和宋清朗相戀三年暮芭,在試婚紗的時候發(fā)現自己被綠了鹿驼。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,902評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡辕宏,死狀恐怖畜晰,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情瑞筐,我是刑警寧澤凄鼻,帶...
    沈念sama閱讀 35,621評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站聚假,受9級特大地震影響块蚌,放射性物質發(fā)生泄漏。R本人自食惡果不足惜膘格,卻給世界環(huán)境...
    茶點故事閱讀 41,220評論 3 328
  • 文/蒙蒙 一峭范、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧瘪贱,春花似錦纱控、人聲如沸游岳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,838評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽胚迫。三九已至,卻和暖如春唾那,著一層夾襖步出監(jiān)牢的瞬間访锻,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,971評論 1 269
  • 我被黑心中介騙來泰國打工闹获, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留期犬,地道東北人。 一個月前我還...
    沈念sama閱讀 48,025評論 2 370
  • 正文 我出身青樓避诽,卻偏偏與公主長得像龟虎,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子沙庐,可洞房花燭夜當晚...
    茶點故事閱讀 44,843評論 2 354

推薦閱讀更多精彩內容

  • 函數聲明和函數表達式有什么區(qū)別鲤妥? 函數聲明和函數表達式是EMACScript規(guī)定的兩種不同的聲明函數的方法。1.函...
    LeeoZz閱讀 347評論 0 1
  • 函數聲明和函數表達式有什么區(qū)別 JavaScript 中需要創(chuàng)建函數的話拱雏,有兩種方法:函數聲明棉安、函數表達式,各自寫...
    蕭雪圣閱讀 954評論 2 2
  • 1.函數聲明和函數表達式有什么區(qū)別 函數聲明 代碼執(zhí)行時函數聲明會被提升到最前執(zhí)行铸抑,所以函數的調用與函數聲明的順序...
    Feiyu_有貓病閱讀 375評論 0 0
  • 如題贡耽,本文介紹函數與作用域的相關知識 1.函數聲明和函數表達式有什么區(qū)別 函數聲明:使用function關鍵字可以...
    hahahahaqwert閱讀 294評論 0 0
  • 也許現在的拖延癥是最煩人的毛病了刁憋。 比如說好的減肥滥嘴,一拖再拖。比如工作一拖再拖职祷,到了deadline才會動起來氏涩,最...
    寶嫻閱讀 368評論 0 1