1. 程式人生 > >簡析JavaScript中的Function型別(四)——函式的內部屬性

簡析JavaScript中的Function型別(四)——函式的內部屬性

開發十年,就只剩下這套架構體系了! >>>   

函式的內部屬性主要有三個:arguments, this, caller。其中this簡析JavaScript中的this關鍵字中探討的已經比較清楚了,這裡來說下argumentscaller

1. arguments

看下面的程式碼:

function sayHello(){
  console.log(arguments[0], arguments[1], arguments[2]);
}
sayHello('Bob', 'Jack', 'Rose');// Bob Jack Rose

如程式碼所示,宣告sayHello時沒有顯式地宣告引數,但是在函式內部依然可以通過arguments訪問傳遞給函式的引數。arguments是一個類陣列物件,包含著傳入函式中的所有引數。

arguments除了可以儲存引數以外,它還有一個名叫callee的屬性,該屬性指向包含arguments的函式,如下程式碼所示:

function sayHello(){
  console.log(arguments.callee);
}
sayHello();
/*
控制檯輸出:
ƒ sayHello(){
      console.log(arguments.callee);
    }
*/

那麼將函式的引用儲存在arguments.callee

中有什麼用處呢?下面是一個使用示例:

//階乘函式
function factorial(num){
  if(num <= 1){
    return 1;
  }else{
    return num * factorial(num - 1);
  }
}
console.log(factorial(4));//24

這種寫法在函式有名字,而且名字以後也不會變的情況下是沒有問題的。但是函式的執行與函式名factorial緊緊耦合在了一起,當函式名發生變化時,呼叫就出現了問題:

var trueFactorial = factorial;
factorial = null;
console.log(trueFactorial(4));//Uncaught TypeError: factorial is not a function

使用arguments.callee可以達到解耦的目的:

function factorial(num){
  if(num <= 1){
    return 1;
  }else{
    return num * arguments.callee(num - 1);
  }
}

var trueFactorial = factorial;
factorial = null;
console.log(trueFactorial(4));// 24

如程式碼所示,無論將來函式名如何變化,始終都能保證正確的執行結果。

2. caller

從字面意思理解,為呼叫者。這個屬性儲存著當前函式的呼叫函式,如果是在全域性作用域中呼叫,它的值為null。來看下面的例子:

function inner(){
  console.log(inner.caller);
}

function outer(){
  inner();
}

inner();// null
outer();// 結果如下:
/*
ƒ outer(){
      inner();
    }
*/

如程式碼所示,在全域性作用域中呼叫時結果為null,在outer中呼叫時結果為outer。同樣,為了解耦合,也可以將inner改寫如下:

function inner(){
  console.log(arguments.callee.caller);
}

需要注意的是嚴格模式是不支援argumentscall