函數(shù)與作用域

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

  • 函數(shù)聲明:function functionName(){};使用function關(guān)鍵字聲明一個(gè)函數(shù),再指定一個(gè)函數(shù)名,叫函數(shù)聲明
    函數(shù)表達(dá)式:var fn = function(){};使用function關(guān)鍵字聲明一個(gè)函數(shù),但未給函數(shù)命名,最后將匿名函數(shù)賦予一個(gè)變量fn,叫函數(shù)表達(dá)式,這是最常見的函數(shù)表達(dá)式語(yǔ)法形式
    -** 區(qū)別
    1.Javascript引擎在解析javascript代碼時(shí)會(huì)‘
    函數(shù)聲明提升’(Function declaration Hoisting)當(dāng)前執(zhí)行環(huán)境(作用域)上的函數(shù)聲明,而函數(shù)表達(dá)式必須等到Javascirtp引擎執(zhí)行到它所在行時(shí),才會(huì)從上而下一行一行地解析函數(shù)表達(dá)式**。
    2.函數(shù)表達(dá)式后面可以加括號(hào)立即調(diào)用該函數(shù),函數(shù)聲明不可以,只能以fnName()形式調(diào)用 。
   alert(foo); // function foo() {} 原因:變量聲明提升
   alert(bar); // undefined:原因bar能提升,但是沒賦值,默認(rèn)為undefined
   function foo() {}   
    var bar = function bar_fn() {};
  alert(foo); // function foo() {}
  alert(bar); // function bar_fn() {}

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

  • 變量的聲明前置:就是在一個(gè)作用域塊中,所有的變量都被放在代碼塊的開始出處聲明
  • 函數(shù)的聲明前置:和變量的聲明會(huì)前置一樣,函數(shù)聲明同樣會(huì)前置。
  • 函數(shù)聲明的前置為:聲明和賦值均前置。
  • 函數(shù)表達(dá)式的前置為:僅僅聲明前置,值為undefined,直到讀到表達(dá)式后才取得表達(dá)式的值。

3.arguments 是什么

arguments是類數(shù)組對(duì)象,包含著傳入函數(shù)中的所有參數(shù)。arguments 變量不是一個(gè)數(shù)組(Array)。 盡管在語(yǔ)法上它有數(shù)組相關(guān)的屬性 length,但它不從 Array.prototype 繼承,實(shí)際上它是一個(gè)對(duì)象(Object)。
因此,無(wú)法對(duì) arguments 變量使用標(biāo)準(zhǔn)的數(shù)組方法,比如 push, pop 或者 slice。

eg:   function printPersonInfo(name, age, sex){ 
            console.log(arguments);
      }
    printPersonInfo("tiger",6,"boy")

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

  • "重載"的概念:,是Ada、C++、C#、D和Java等編程語(yǔ)言中具有的一項(xiàng)特性,這項(xiàng)特性允許創(chuàng)建數(shù)項(xiàng)名稱相同但功能的輸入輸出類型不同的子程序,它可以簡(jiǎn)單地稱為一個(gè)單獨(dú)功能可以執(zhí)行多項(xiàng)任務(wù)的能力。
 其他語(yǔ)言的重載;
  int sum(int num1, int num2){
      return num1 + num2;
     }
  float sum(float num1, float num2){
    return num1 + num2;
  }
  sum(1, 2);
  sum(1.5, 2.4);
  • 在 JS 中沒有重載! 同名函數(shù)會(huì)覆蓋。 但可以在函數(shù)體針對(duì)不同的參數(shù)調(diào)用執(zhí)行相應(yīng)的邏輯
    function printPeopleInfo(name, age, sex){
    if(name){
    console.log(name);
    }
    if(age){
    console.log(age);
    }
    if(sex){
    console.log(sex);
    }
    }
    printPeopleInfo('Byron', 26); // 'Byron' 26
    printPeopleInfo('Byron', 26, 'male');// 'Byron' 26 'male'

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

  • 英文:immediately-invoked function expression,縮寫:IIFE,是一種利用JavaScript函數(shù)生成新作用域的編程方法。有時(shí),這種編程方法也被叫做“自執(zhí)行(匿名)函數(shù)”,但“立即調(diào)用函數(shù)表達(dá)式”是語(yǔ)義上最準(zhǔn)確的術(shù)語(yǔ)。
  • 作用
    隔離作用域,保護(hù)私有變量,防止污染全局變量
  • 用法
    最常見的一種是將函數(shù)表達(dá)式字面量置于圓括號(hào)之內(nèi),然后使用圓括號(hào)調(diào)用函數(shù)。
    (置于圓括號(hào)內(nèi)是因?yàn)椋簾o(wú)論在全局環(huán)境或者局部環(huán)境里遇到了這樣的function關(guān)鍵字,默認(rèn)的,它會(huì)將它當(dāng)作是一個(gè)函數(shù)聲明,而不是函數(shù)表達(dá)式,如果你不明確的告訴圓括號(hào)它是一個(gè)表達(dá)式,它會(huì)將其當(dāng)作沒有名字的函數(shù)聲明并且拋出一個(gè)錯(cuò)誤,因?yàn)楹瘮?shù)聲明需要一個(gè)名字)
    (function() { // 這里的語(yǔ)句將獲得新的作用域 })(); 若要將作用域外變量傳遞進(jìn)函數(shù),則按下述方式書寫: (function(a, b) { // a == 'hello' // b == 'world' })('hello', 'world'); 在一些省略分號(hào)的程序中,可見將分號(hào)至于行首的做法。這樣的分號(hào)被稱為“防御性分號(hào)” a = b + c ;(function() { // 故意將分號(hào)放在這里 // 代碼 })(); 如此書寫,以防止語(yǔ)句被理解為對(duì)函數(shù)c的調(diào)用(c(...))。

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

 function factorial(n){
    if(n<0){
      return "無(wú)效輸入";
    }
    else if(n<=1){
        return 1;
    }else{
        return n*factorial(n-1) ;
    }
 }
  alert(factorial(5))//120

7.以下代碼輸出什么?

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, '男');
> getInfo('小谷', 3);
> getInfo('男');

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

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

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

console.log(a); //undefined ;變量a聲明提前,但未賦值 
var a = 1;
console.log(b);//b is not defined ;變量b沒有聲明和賦值

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

sayName('world');// hello  world;函數(shù)聲明的前置為聲明和賦值均前置
sayAge(10);//sayAge is not a function ;函數(shù)聲明前置,但表達(dá)式值不能前置,sayAge為undefined,undefined 沒有方法。
function sayName(name){
    console.log('hello ', name);
}
var sayAge = function(age){
    console.log(age);
};

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

  var x = 10
  bar() //返回:10
  function foo() {
    console.log(x)
  }  
  function bar(){
    var x = 30
    foo()
}
globalContext={
  Ao:{
    x:10
    foo:function
    bar:function
  } ,
Scope:null
}
  //聲明 foo 時(shí) 得到下面
  foo.[[scope]] = globalContext.Ao
  //聲明 bar 時(shí) 得到下面
  bar.[[scope]] = globalContext.Ao
  //當(dāng)調(diào)用 bar() 時(shí), 進(jìn)入 bar 的執(zhí)行上下文
  barContext ={
      Ao:{
         x:30
      },
      Scope:bar.[[scope]]// globalContext.Ao
  }
當(dāng)調(diào)用 foo() 時(shí),先從 bar 執(zhí)行上下文中的 AO里找,找不到再?gòu)?bar 的 [[scope]]里找找到后即調(diào)用
  //當(dāng)調(diào)用 foo() 時(shí),進(jìn)入 foo 的執(zhí)行上下文
  fooContext = {
      AO: {},
      Scope: foo.[[scope]] // globalContext.AO
  }
        所以 console.log(x)是 10

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

var x = 10;
bar() //返回30
function bar(){
    var x = 30;
    function foo(){
      console.log(x) 
}
  foo();
}   
 作用域查找過(guò)程偽代碼
globalContext={
  Ao:{
    x:10
    bar:function
  } ,
Scope:null
}

  //聲明 bar 時(shí) 得到下面
  bar.[[scope]] = globalContext.Ao
  //當(dāng)調(diào)用 bar() 時(shí), 進(jìn)入 bar 的執(zhí)行上下文
  barContext ={
      Ao:{
         x:30,
        foo:function
      },
      Scope:bar.[[scope]]// globalContext.Ao
  }
當(dāng)調(diào)用 foo() 時(shí),先從 bar 執(zhí)行上下文中的 AO里找,找到后即調(diào)用
  //當(dāng)調(diào)用 foo() 時(shí),進(jìn)入 foo 的執(zhí)行上下文
  fooContext = {
      AO: {},
      Scope: foo.[[scope]] // barContext.AO
  }
        所以 console.log(x)是 30

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

var x = 10;
bar() // 30
function bar(){
  var x = 30;
    (function (){
    console.log(x)
  })()
}
作用域鏈的查找過(guò)程偽代碼
 globalContext = {
      Ao:{
        x:30
        bar:function
    },
      Scope:null
  }
 // 聲明bar時(shí),得到下面
  bar.[[scope]]=globalContext.Ao;
  //當(dāng)調(diào)用bar時(shí),進(jìn)入bar的執(zhí)行上下文;先從 bar 執(zhí)行上下文中的 AO里找,找到后即調(diào)用
   barContext = {
      Ao:{
        x:30
        IIFE:function
      }
      Scope: bar.[[scope]]//globalContext.Ao
    }
  所以 console.log(x)是 30

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

var a = 1;
function fn(){
  console.log(a)//undefined
  var a = 5
  console.log(a)//5
   a++
   var a
   fn3()  
   fn2() 
   console.log(a) //20
   function fn2(){
    console.log(a)  //6
    a = 20   
  }
}
function fn3(){
  console.log(a)   //1
  a = 200
}
fn() //20
console.log(a)  //200
 //作用域鏈查找過(guò)程偽代碼
globalContext = {
    Ao:{
        a:200
        fn:function 
        fn3:function
    },
    Scope:null
  }
 // 聲明fn時(shí),得到下面
fn.[[scope]] = globalContext .Ao
// 聲明fn3時(shí),得到下面
fn3.[[scope]] = globalContext .Ao


 fnContext={
    Ao:{
      a:20
      fn2:function
    }
    Scope:fn.[[scope]]// globalContext .Ao
  }

 fn3Context={
    Ao:{}
    Scope:fn.[[scope]]// globalContext .Ao
}

   // 聲明fn2時(shí),得到下面
    fn2.[[scope]] = fnContext .Ao
  
    fn2Context={
          Ao:{}
          Scope:fn.[[scope]]// fnContext .Ao
    }
所以 fn()是20  console.log(a)是200
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1. 函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別 使用function關(guān)鍵字聲明一個(gè)函數(shù)時(shí),聲明不必放到調(diào)用的前面。//函數(shù)聲...
    _李祺閱讀 329評(píng)論 0 0
  • 函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別? 函數(shù)聲明和函數(shù)表達(dá)式是EMACScript規(guī)定的兩種不同的聲明函數(shù)的方法。1.函...
    LeeoZz閱讀 439評(píng)論 0 1
  • 1,函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別 1、背景介紹 定義函數(shù)的方法主要有三種: 1:函數(shù)聲明(Function De...
    進(jìn)擊的前端_風(fēng)笑影閱讀 488評(píng)論 0 0
  • 聲明前置和作用域也是JS 部分面試??键c(diǎn) 1.函數(shù)聲明和函數(shù)表達(dá)式有什么區(qū)別 函數(shù)聲明:使用function關(guān)鍵字...
    湖衣閱讀 265評(píng)論 0 0
  • 目標(biāo):1、希望孩子擁有更多朋友更加開心快樂!智慧多多!不計(jì)較!不抱怨! 2、希望我的學(xué)習(xí)可以讓我通過(guò)稅一稅二考試。...
    zl向日葵閱讀 139評(píng)論 0 0

友情鏈接更多精彩內(nèi)容