JS函數(shù)與作用域

如題,本文介紹函數(shù)與作用域的相關(guān)知識(shí)

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

  • 函數(shù)聲明:使用function關(guān)鍵字可以聲明一個(gè)函數(shù)

    例:function foo(){}

  • 函數(shù)表達(dá)式:意即將一個(gè)匿名函數(shù)賦值給一個(gè)變量

    例:var foo=function(){}

  • 區(qū)別:

    (1)函數(shù)聲明必須有標(biāo)識(shí)符,也就是常說的函數(shù)名;函數(shù)表達(dá)式可以省略函數(shù)名

    (2)函數(shù)的聲明不必放到調(diào)用的前面,函數(shù)調(diào)用的時(shí)候才會(huì)被執(zhí)行。函數(shù)的表達(dá)式則必須放到調(diào)用的前面。

    (3)函數(shù)聲明在JS解析時(shí)進(jìn)行函數(shù)提升,因此在同一個(gè)作用域內(nèi),不管函數(shù)聲明在哪里定義,該函數(shù)都可以進(jìn)行調(diào)用。而函數(shù)表達(dá)式的值是在JS運(yùn)行時(shí)確定,并且在表達(dá)式賦值完成后,該函數(shù)才能調(diào)用。

    在程序執(zhí)行前,會(huì)先獲取函數(shù)聲明聲明的函數(shù),獲取變量的聲明,這里變量的聲明只是先開辟一個(gè)空間,然后給了個(gè)名字,之后到該變量名賦值的時(shí)候,才有值,也就是說,在未得到該變量的賦值前,使用該變量會(huì)得到undefined。

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

  • javascript的變量聲明具有hoisting機(jī)制,JavaScript引擎在執(zhí)行的時(shí)候,會(huì)把所有的聲明都提升到當(dāng)前作用域的最前面

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

    變量的聲明前置,在程序運(yùn)行前,先獲取變量的名字,到該變量的賦值語句,才為該變量賦值,再此前都是undefined

  • 函數(shù)的聲明前置:function 函數(shù)名(){}聲明了一個(gè)函數(shù),在程序運(yùn)行前,提取所有函數(shù)聲明的函數(shù),之后才正式開始運(yùn)行函數(shù),所以,無論函數(shù)聲明的函數(shù)執(zhí)行語句放在程序的最前面,或者程序的最后面,都能夠正常執(zhí)行

3.arguments 是什么

arguments是函數(shù)內(nèi)部的一個(gè)對(duì)象,對(duì)應(yīng)著傳進(jìn)來的參數(shù),是一個(gè)類數(shù)組對(duì)象,沒有數(shù)組的操作方法。

  • 特點(diǎn):

(1)對(duì)象有l(wèi)ength屬性且length的值就是對(duì)象里屬性的數(shù)量

(2)每個(gè)傳進(jìn)來的參數(shù)對(duì)應(yīng)著arguments[0],arguments[1],有先后順序之分,通過下標(biāo)獲取到對(duì)應(yīng)值

比如

function fn(name,age){

console.log(arguments[0];);

console.log(arguments[1];);

}

4.函數(shù)的"重載"怎樣實(shí)現(xiàn)

  • 定義:重載函數(shù)就是在同一作用域內(nèi),可以有一組具有相同函數(shù)名,不同參數(shù)列表的函數(shù),執(zhí)行相應(yīng)的功能

  • 在JS中沒有函數(shù)重載。相同的函數(shù)名字,如果定義的參數(shù)個(gè)數(shù)不一樣,后出現(xiàn)的會(huì)覆蓋先出現(xiàn)的 同名函數(shù)后面的會(huì)覆蓋前面的。

  • 但我們可以通過在函數(shù)體內(nèi)針對(duì)不同的參數(shù)調(diào)用執(zhí)行相應(yīng)的邏輯,也就類似實(shí)現(xiàn)了“重載”的效果。

     例子
      function printPeopleInfo(name, age, sex){
       if(name){
       console.log(name);
      }
    
       if(age){
       console.log(age);
      }
    
      if(sex){
       console.log(sex);
      }
      }
    
      printPeopleInfo('Byron', 26);
      printPeopleInfo('Byron', 26, 'male');
    

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

  • 寫法

(1)(function(){ /* code */ }()); // Crockford 推薦這個(gè)

(2)(function(){ /* code */ })(); // 這個(gè)同樣運(yùn)行正常

  • 作用

(1) 函數(shù)會(huì)立即執(zhí)行。

(2) 隔離作用域(這個(gè)匿名函數(shù)中的變量與外部環(huán)境的變量隔離,防止了變量的命名沖突,形成了一個(gè)獨(dú)立的空間,有助于代碼模塊化。)

6.求n!,用遞歸來實(shí)現(xiàn)

  • 遞歸4個(gè)特點(diǎn):

(1)自己調(diào)用自己

(2)設(shè)定終止條件

(3)優(yōu)點(diǎn):算法簡單

(4)缺點(diǎn):效率低

  • 例子

    function factor(n){
    if(n===1){
    console.log(n);
    return n;
    }
    var nn=n*factor(n-1)
    console.log(nn)
    return nn
    }  
    factor(5)````
    

    //1*2*3*4*5 結(jié)果:1 2 6 24 120

7.以下代碼輸出什么?(PS: //注釋就是結(jié)果)

   function getInfo(name, age, sex){
   console.log('name:',name);     //饑人谷-->小谷-->男
   console.log('age:', age);      //2-->3-->undefined
   console.log('sex:', sex);      //男-->undefined-->undefined
   console.log(arguments);        //空(沒有指定下標(biāo))
   arguments[0] = 'valley';   
   console.log('name', name);     //name valley 
   }
   getInfo('饑人谷', 2, '男');
   getInfo('小谷', 3);
   getInfo('男');

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

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

9.如下代碼的輸出?為什么

   console.log(a);
   var a = 1;   //undefined
   console.log(b); //報(bào)錯(cuò)
  • 結(jié)果:undefined和報(bào)錯(cuò)
  • 原因:
    (1)變量a的定義var a = 1; 應(yīng)該放到 console.log(a); 的前面,變量應(yīng)該先定義后輸出。
    (2)b是沒有被聲明的,肯定不能直接輸出。

10.如下代碼的輸出?為什么

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

輸出 :hello,world以及報(bào)錯(cuò)
原因:
function sayName(name){} 是一個(gè)函數(shù),它可以直接調(diào)用賦值,聲明和調(diào)用不分先后,沒有順序
var sayAge = function(age){} 是一個(gè)函數(shù)表達(dá)式,想要賦值必須先要聲明,應(yīng)該放到function(age){}后面

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

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

   /*
 1.第一步:執(zhí)行上下文

  globalContext{
    AO:{
     x=10;
     foo:function();
     bar:function();
   },
    Scope:null
  }

  foo.[[scope]]=globalContext.AO
  bar.[[scope]]=globalContext.AO

 2.第二步:調(diào)用bar()

  barContext={
    AO:{
     x:30
     foo:function
    },
    Scope:bar.[[scope]]//globalContext.AO
  }

   bar()  //結(jié)果 x:30

 3.第三步:調(diào)用foo()

  fooContext={
    AO:{}
    Scope:foo.[[scope]]=globalContext.AO
   }
    foo()  //結(jié)果 x:10

    //最終結(jié)果: x:10
   */

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

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


 /*
  第一步:執(zhí)行上下文
  globalContext{
    AO:{
     x:10
     bar:function
    }
    Scope:null
  }
  bar.[[scope]]=globalContext.AO

  第二步:調(diào)用bar()

   barContext={
     AO:{
      x:30
      foo:function
     }
     Scope:bar.[[scope]]=globalContext.AO
   }

  bar()  //結(jié)果 x:30

  第三步:調(diào)用foo()

  fooContext={
    A0:{ }
    Scope:foo.[[scope]]=barContext.AO
  }

  foo() //結(jié)果 x:30

//  bar(){
//  foo()
//  }
//  最終結(jié)果 x:30
*/

13. 以下代碼輸出什么? 寫出作用域鏈的查找過程偽代碼

   var x = 10;
   bar() 
   function bar(){
   var x = 30;
   (function (){
   console.log(x)
   })()
   }


   /*
   第一步:執(zhí)行上下文

   globalContext{
     AO:{
       x:10;
       bar:function
     }
     Scope:null
   }

   bar.[[scope]]=globalContext.AO

   第二步:調(diào)用bar()

   barContext={
     AO:{
       x=30
       :function
     }
     Scope:bar.[[scope]]=globalContext.AO
   }

   第三步:立即執(zhí)行function ()

   functionContext={
     AO:{  }
     Scope:function.[[scope]]//barContext.AO
   }

 //  最終結(jié)果  x:30
*/

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

   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()
   console.log(a)


   /*
   //第一步:執(zhí)行上下文
   globalContext:{
     AO:{
       a:1
       fn:function
       fn3:function
     } 
     Scope:null
   }

    fn.[[scope]]=globalContext.A0
    fn3.[[scope]]=globalContext.AO

   //調(diào)用 fn()
   fnContext:{
     AO:{
       a:6
       fn3:function
       fn2:function
     }
    Scope:null
   }
    fn3[[scope]]=fnContext.AO
    fn2[[scope]]=fnContext.AO

   //調(diào)用 fn2()
   fn2Context:{ 
     AO:{  
    }
     Scope:fn2.[[scope]]=fnContext.AO
   }

   //調(diào)用 fn3()
   fn3Context:{
     AO:{
     } 
     Scope:fn3.[[scope]]=globalContext.AO
   }

   // 最終結(jié)果 a:undefined 5 1 6  20 200

 */

本文部分內(nèi)容來自于饑人谷,版權(quán)歸饑人谷_海瀚和饑人谷所有,轉(zhuǎn)載需說明來源

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,885評(píng)論 6 541
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,312評(píng)論 3 429
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,993評(píng)論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,667評(píng)論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,410評(píng)論 6 411
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,778評(píng)論 1 328
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,775評(píng)論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,955評(píng)論 0 289
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,521評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,266評(píng)論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,468評(píng)論 1 374
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,998評(píng)論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,696評(píng)論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,095評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,385評(píng)論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 52,193評(píng)論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,431評(píng)論 2 378

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

  • 函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別? 函數(shù)聲明和函數(shù)表達(dá)式是EMACScript規(guī)定的兩種不同的聲明函數(shù)的方法。1.函...
    LeeoZz閱讀 353評(píng)論 0 1
  • JavaScript中的函數(shù)運(yùn)行在它們被定義的作用域里,而不是它們被執(zhí)行的作用域里。 函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)...
    畢子歌閱讀 406評(píng)論 0 0
  • 函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別 JavaScript 中需要?jiǎng)?chuàng)建函數(shù)的話,有兩種方法:函數(shù)聲明、函數(shù)表達(dá)式,各自寫...
    蕭雪圣閱讀 963評(píng)論 2 2
  • 1.函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別 函數(shù)聲明 代碼執(zhí)行時(shí)函數(shù)聲明會(huì)被提升到最前執(zhí)行,所以函數(shù)的調(diào)用與函數(shù)聲明的順序...
    Feiyu_有貓病閱讀 397評(píng)論 0 0
  • 我想 要你看 看春風(fēng)拂面 嫩柳輕輕地飄舞 我想 要你聽 聽花開鳥鳴 迎春花遍地歡唱 我想你在那花叢里 舞出你的顏色...
    虛實(shí)先森閱讀 176評(píng)論 0 9