在函数的内部,有两个特殊的对象:arguments和this。arguments是一个类数组对象,它包含所有传入这个函数的所有参数;它有一个属性callee,callee是一个指针,指向拥有这个arguments对象的函数。
以下是非常经典的乘阶函数代码:
function factorial(num) {
if (num <= 1) {
return 1;
}else{
return num * factorial(num - 1);//此段代码亦可写成arguments.callee(num - 1);
}
}
this引用的是函数据以执行的环境对象——或者可以说是this的值。
ES5中定义了函数的另一个对象属性: caller。这个函数保存着调用当前函数的函数引用,如果在全局环境中调用当前函数,它的值为null,例:
function outer() {
inner();
}
function inner() {
alert(arguments.callee.caller);
}
outer();
这段代码会弹出outer();的源码。注意:在严格模式下方为arguments.callee会导致错误。
每个函数都有length和prototype属性,其中length表示函数希望接收的命名参数的个数,来个栗子:
function sayName(name) {
alert(name);
}
alert(sayName.length); //1
每个方法都有两个非集成而来的方法:apply()和call().
apply()接收两个参数:一个是函数的作用域,第二个是参数数组,第二个参数可以是数组实例,也可以是arguments对象。apply()和call()的作用相同,他们的区别在于接收参数的方式不同。call的第一个参数值是this没有变化,变化的是call其余参数都是直接传递给函数,也就是其余参数都必须一一列举出来。例子:
function sum (num1 + num2) {
return num1 + num2;
}
function callNum(num1,num2) {
return sum.call(this,num1,num2);
}
alert(callSum(callSum(10,10))); //20 在使用call()时,callSum()必须明确传递参数。
call()和apply()真正强大的作用在于,他们能够扩展函数赖以运行的作用域。
例子:
window.color = 'red';
var o = {color: 'blue'};
function sayColor() {
console.log(this.color);
}
sayColor();//red
sayColor.apply(this);//red
sayColor.call(window);//red
sayColor.call(o);//blue