函數聲明與函數表達式

定義函數的方式有2種:
  1. 函數聲明
  2. 函數表達式
函數聲明的形式
function functionName(arg1,arg2){}

  

關於函數聲明,它有一個重要的特性就是函數聲明提高,意思是在執行代碼以前會先讀取函數聲明。
這就意味着能夠把函數聲明放在調用它的語句後面。
<script>
sayHi();
function sayHi(){
 alert("hi,world")
}
console.log(sayHi.name) //輸出sayHi,這是sayHi(){} 的name
</script>

  

這個例子不會拋出錯誤,由於在代碼執行以前會讀取函數聲明。
第二種建立函數的方式是使用函數表達式。
最多見的建立方式:
var functionName = function(arg1,arg2){}

  

這種形式看起來好像是常規的變量賦值語句,即建立一個函數並將它賦值給變量functionName
。這種狀況下建立的函數是匿名函數,由於function 關鍵字後面沒有標識符。
匿名函數的name屬性是空字符串。這也是能夠理解的,畢竟是匿名函數嘛。
<script>
 
sayBye();
var sayBye = function(){
alert("byebye");
}
</script>
報錯:sayBye is not a function

  

理解函數提高的關鍵,就是理解函數聲明與函數表達式之間的區別。
<script>
 
var flag;
if(flag){
function sayHi(){
alert('hi');
}
}else{
function sayHi(){
alert('love');
}
};
sayHi(); //彈出 love
</script>

  

表面上看flag的布爾值true就是用一個sayHi()定義,不然就是用另外一個定義。
實際上這在ECMAScript中屬於無效語法,javascript引擎會嘗試修正錯誤,將其轉換爲合理的狀態。
可是瀏覽器嘗試修正錯誤的作法並不一致。大多數瀏覽器會返回第二個聲明,忽略condition,但chrome,火狐,opera,會在flag爲true時,返回以一個函數聲明;所以使用這種方法很危險,不該該出如今你的代碼中。不過,若是是使用函數表達式就沒有什麼問題了。
<script>
var sayBye;
var flag;
if(flag){
sayBye = function(){
alert("bye");
}
}else{
sayBye = function(){
alert("bye lizi");
}
};
sayBye(); //彈出 bye lizi
</script>
也能夠這樣寫:
<script>
 
function mult(num){
if(num<=0){
  return num = 1;
}else{
  return num * arguments.callee(num-1);
}
};
 
 
 
alert(mult(3)) ;
</script>

  

arguments.callee指向一個正在執行的函數的指針,所以能夠用它來實現對函數的遞歸調用
經過使用arguments.callee代替函數名,能夠確保不管怎樣調用函數都不會出問題。所以,在編寫地櫃函數時,使用arguments.callee總比使用函數名更保險。
但在嚴格模式下,不能經過腳本方位arguemnts.callee,訪問這個屬性會致使錯誤
<script>
'use strict';
function mult(num){
if(num<=0){
  return num = 1;
}else{
  return num * arguments.callee(num-1);
}
};
alert(mult(3)) ; //'caller', 'callee', and 'arguments' properties may not be accessed on strict mode //functions
</script>

  

不過,可使用命名函數表達式來達成相同的結果。
<script>
var interation = (function f(num){
if(num <=1){
  return num = 1;
}else{
  return num * f(num-1);
}
})
 
alert(interation(3));
</script>

  

以上代碼建立了一個名爲f()的命名函數表達式,而後將它賦值給變量interation.即便把函數賦值給了另外一個變量,函數的名字f仍然有效,因此遞歸調用照樣能正常完成。這種方式在嚴格模式和非嚴格模式下都行得通。
相關文章
相關標籤/搜索