JavaScript關于函數

問答

函數聲明和函數表達式有什么區別 (*)

函數聲明形式:

function sayHello(){
  console.log("Hello, World! ");
}

函數表達式形式:

var sayHello = function(){
  console.log("Hello, World! ");
};

在聲明一個變量的時候,javascript解釋器會將變量聲明的語句提前,函數聲明形式會發生函數聲明前置,所以代碼如果放在使用之后也可以生效,而函數表達式形式只發生了變量聲明前置,如果在定義之前使用,函數名目前還只是一個變量名,不能用()進行執行,會拋出錯誤。

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

var a = 1;
//實際上相當于:
var a; //這句聲明會提前到所有語句之前執行
a=1;

所以,

console.log(b); 
var b = 1;//console.log 并不會報錯,而是返回變量聲明之后的值undefined。

arguments 是什么 (*)

arguments 是一個可以接收所有函數傳遞參數的類似數組,在函數里可以直接取用。當函數的參數不確定數量的時候可以使用arguments對形參進行數組的方式操作,可以實現類似重載。

函數的重載怎樣實現 (**)

function fn(){ 
  var sum = 0; 
  for(x in arguments ){
    sum=arguments[x]+sum;
  };
  console.log(sum);
}
//無論多少參數都可實現累加運算

立即執行函數表達式是什么?有什么作用 (***)

(function() {
  c =1 ;
  console.log(c)
})();

立即執行函數可以將寫在函數體內的語句直接執行。區別于普通語句,立即執行函數內的變量不會干擾函數體外,形成一個類似區塊的空間。

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

函數對象其中一個內部屬性是[[Scope]],由ECMA-262標準第三版定義,該內部屬性包含了函數被創建的作用域中對象的集合,這個集合被稱為函數的作用域鏈,它決定了哪些數據能被函數訪問。
在函數執行過程中,每遇到一個變量,都會經歷一次標識符解析過程以決定從哪里獲取和存儲數據。該過程從作用域鏈頭部,也就是從活動對象開始搜索,查找同名的標識符,如果找到了就使用這個標識符對應的變量,如果沒找到繼續搜索作用域鏈中的下一個對象,如果搜索完所有對象都未找到,則認為該標識符未定義。函數執行過程中,每個標識符都要經歷這樣的搜索過程。


--JavaScript 開發進階:理解 JavaScript 作用域和作用域鏈]

簡單來說,函數作用域鏈用于查找函數內部變量的位置。在執行過程中,按照作用域鏈表的順序依次進行查找。在函數每執行一次,這個表進行動態創建。所以,在實際使用中應當盡量減少全局變量的使用,避免with語句使用,如果一個跨作用域的對象被引用了一次以上,則先把它存儲到局部變量里再使用。


代碼

  1. 以下代碼輸出什么? (難度**)

  • 可以看出arguments 是參數的數組,可以對其進行修改,改變參數。
  • 當參數缺省的時候,定義為 undefined。
  • 參數是具有順序的,第一個參數傳遞為第一個形參。
  1. 寫一個函數,返回參數的平方和?如 (難度**)

function sumOfSquares(){
  var sum = 0;
  for(var x in arguments){
    sum += arguments[x]*arguments[x];
  }
  console.log(sum);
}

sumOfSquares(2,3,4);   // 29
sumOfSquares(1,3);   // 10
  1. 如下代碼的輸出?為什么 (難度*)

console.log(a);//返回 undefined
var a = 1;
console.log(b);//報錯 提示未定義

因為聲明前置,實際上在這段代碼執行前就已經執行了var a;,所以在console.log(a)的時候不發生錯誤,返回undefined。

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

  • 由于函數聲明前置,sayName可以正常執行
  • sayAge用了函數表達式形式,在賦值之前都不可以使用。

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

function fn(){}
var fn = 3;
console.log(fn);//3

結果比較直觀,實際上將上面的語句顛倒也會輸出相同的結果:

var fn = 3;
function fn(){}
console.log(fn);//3
  • 還是因為聲明前置的原因,可以將聲明都放到開頭,再來理解:
var fn;
function fn(){}

fn = 3;
console.log(fn);//3

這就是上面那段代碼實際執行的樣子,這也就不難理解了。
需要注意的是,聲明前置,變量的聲明要比函數的聲明要更早執行。

  function fn(){}
  var fn;  
  console.log(fn);

//function fn(){}

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

  • 在函數內部定義的函數,也會發生聲明前置。上圖中即使傳入了參數10,但與函數內部函數重名,被覆蓋掉了。此時console.log(fn2),打印出的就是fn2函數本身。此后fn2被重新賦值2,打印出3。

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

var fn = 1;
function fn(fn){
   console.log(fn);
}
console.log(fn(fn)); 

//Uncaught TypeError: fn is not a function(…)

實際執行過程,由于聲明前置:

var fn;
function fn(fn){
   console.log(fn);
}

fn = 1;
console.log(fn(fn)); 

fn被重新賦值為1,自然無法執行,報錯。

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
  • 需要注意的是,for是屬于運算符,不屬于函數,所以在其內部定義的變量和當前屬于同一個作用域。在JS中只有函數內部使用var定義,才具備另一個作用域性質。

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;
    }
}

改寫代碼:

var i;
var fn;
function fn(){
    var i;
    function fn2(){
        i = 100;
    }

    console.log(i);//undefined
    i = 99;
    fn2();
    console.log(i);//100
    
}

fn(); 
//undefined
//100
i = 10;
fn = 20;
console.log(i);//10

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

  • 立即執行函數的內部定義的函數名、變量不會影響到函數外面。所以在其內部執行的say(),并沒有覆蓋函數外的say = 0; 在最后打印出來還是0 。
  • 函數內部有一個嵌套結構。使用嵌套時,函數名可以在function后定義。不需要的時候可以不加。
  • return的執行,伴隨函數的退出,不再繼續往下執行。

本教程版權歸屬于 張宇 及 饑人谷 所有,轉載請說明來源~

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 今天是函數基礎部分!有點心理準備!老規矩,先放思維導圖!圖片哪里不懂,結合下面文字對應理解! 認識函數 在一個完整...
    范小飯_閱讀 385評論 1 9
  • 一、函數聲明和函數表達式有什么區別?(*) ECMAScript里面規定了三種聲明函數的方式: 構造函數函數也是對...
    婷樓沐熙閱讀 478評論 0 2
  • 問答: 1. 函數聲明和函數表達式有什么區別 (*) 在日常的任務中,JavaScript主要使用下面兩種方式創建...
    小木子2016閱讀 330評論 0 0
  • 朋友一生一起走 那些日子不再有 一句話 一輩子 一生情 一杯酒 朋友不曾孤單過 一聲朋友你會懂 還有傷 還有痛 還...
    21不思量閱讀 211評論 0 0
  • Workflow真的是iOS上的一款效率神器,可以簡化很多步驟,同時可以創造出很多有趣的功能。我也根據自己的需求,...
    Icebay閱讀 1,063評論 0 0