在JavaScript函数内部,有两个特殊的对象: arguments
和 this
, arguments
是一个类数组对象,包含传入函数中的所有对象。 arguments
还有一个 callee
的属性,该属性是一个指针,指向拥有这个 arguments
对象的函数。
arguments
首先来看一个经典的阶乘函数
function factorial(num) {
if (num <= 1) {
return 1;
} else {
return num * factorial(num - 1);
}
}
由于JavaScript中的函数是对象,其存在被重新复制的风险,所以此时我们可以使用 arguments.callee
来进行递归调用,这样就可以做到函数的执行和函数名解耦。
function factorial(num) {
if (num <= 1) {
return 1;
} else {
return num * arguments.callee(num - 1);
}
}
var trueFactorial = factorial;
factorial = function () {
return 0;
};
console.log(factorial(5)); // 0
console.log(trueFactorial(5)); // 120
注:查询MDN得知,这一特性已经过时,不推荐大家使用,仅作为了解使用。
this
this 引用的是函数执行的环境对象(在网页的全局作用域中调用函数时,this对象引用的是window)
window.color = 'red';
function sayColor() {
console.log(this.color);
}
sayColor();
var o = {color: 'blue'};
o.sayColor = sayColor;
o.sayColor();
call
call
与 apply
都是函数非继承来的方法,其用途都是在特定的作用域中调用函数,实际上等于设置函数体内this对象的值。 call
与 apply
唯一不同的地方在于 call 必须将所有参数单独传入,apply
可以传入数组或者 arguments
可以看一下代码示例了解call的用法
window.color = "red";
var o = { color: "blue" };
function sayColor(){
alert(this.color);
}
sayColor(); //red
sayColor.call(this); //red
sayColor.call(window); //red
sayColor.call(o); //blue
可以实现链式构造器(chain constructor)
function Product(name, price) {
this.name = name;
this.price = price;
}
function Food(name, price) {
Product.call(this, name, price);
this.category = 'food';
}
console.log(new Food('cheese', 5).name);
// expected output: "cheese"
call
可以绑定 this
和 obj
function greet() {
var reply = [this.animal, 'typically sleep between', this.sleepDuration].join(' ');
console.log(reply);
}
var obj = {
animal: 'cats', sleepDuration: '12 and 16 hours'
};
greet.call(obj); // cats typically sleep between 12 and 16 hours
console.log(Math.max(1, 2, 3, 5, 6,));
var vaules = [1, 2, 3, 3, 4, 5, 6, 7, 12];
console.log(Math.max.apply(Math, vaules));
以上案例都来自参考中的链接,这里只举出部分重要例子,详细读者可以参阅文档。