函数的内部属性主要有三个:arguments, this, caller
。其中this
在简析JavaScript中的this关键字中探讨的已经比较清楚了,这里来讲下arguments
和caller
。javascript
看下面的代码:java
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
中有什么用处呢?下面是一个使用示例:this
//阶乘函数 function factorial(num){ if(num <= 1){ return 1; }else{ return num * factorial(num - 1); } } console.log(factorial(4));//24
这种写法在函数有名字,并且名字之后也不会变的状况下是没有问题的。可是函数的执行与函数名factorial
牢牢耦合在了一块儿,当函数名发生变化时,调用就出现了问题:.net
var trueFactorial = factorial; factorial = null; console.log(trueFactorial(4));//Uncaught TypeError: factorial is not a function
使用arguments.callee
能够达到解耦的目的:code
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
如代码所示,不管未来函数名如何变化,始终都能保证正确的执行结果。对象
从字面意思理解,为调用者。这个属性保存着当前函数的调用函数,若是是在全局做用域中调用,它的值为null
。来看下面的例子:blog
function inner(){ console.log(inner.caller); } function outer(){ inner(); } inner();// null outer();// 结果以下: /* ƒ outer(){ inner(); } */
如代码所示,在全局做用域中调用时结果为null
,在outer
中调用时结果为outer
。一样,为了解耦合,也能够将inner
改写以下:ip
function inner(){ console.log(arguments.callee.caller); }
须要注意的是严格模式是不支持arguments
和caller
属性的。