ECMAScript 的 arguments 和 this

75 阅读2分钟

「这是我参与2022首次更文挑战的第18天,活动详情查看:2022首次更文挑战

前言

“就像我们说,读万卷书和行万里路,是静态和动态的互补一样。如果说人类的进化,是从行路开始的,那么人类的文明,毫无疑问依靠的是阅读”。最近发现自己很难静下心来读文字,这点需要纠正。今天学到了ECMAScript函数内部的两个特殊的对象:arguments 和 this。

arguments

这个对象之前也了解过了,它是一个类数组对象,包含调用函数时传入的所有参数,并且它只有以function关键字定义函数时才会有,虽然它主要用于包含参数,但是arguments对象其实还有一个callee属性,是一个指向arguments对象所在函数的指针。例如下面这个经典的阶乘函数:

function jc(num){
    if(num <= 1){
        return 1;
    }else{
        return num * jc(num - 1);
    }
}

上述阶乘函数定义为了递归调用,它需要保证函数名为 jc ,这样就导致了紧密耦合。使用arguments.callee属性就可以让函数逻辑和函数名解耦:

function jc(num){
    if(num <= 1){
        return 1;
    }else{
        return num * arguments.callee(num - 1);
    }
}
let anotherJc = jc;
jc = function(){
    return 0;
};
console.log(anotherJc(5));//输出 120
console.log(jc(5));//输出 0

可以看到无论函数名称是什么,递归计算阶乘都可以正确计算。

this

另一个特殊的对象是 this,它在标准函数和箭头函数中又不一样的地方:

  • 标准函数中,this指向的是把函数当成方法调用的上下文对象(在网页的全局上下文中调用函数时,this指向windows),例如:
windows.color = 'green';
let o = {
    color: 'blue'
};
function showColor{
    console.log(this.color);
}
showColor();//输出 'green'
o.showColor = showColor;
o.showColor();//输出 'blue'

可以看到this到底引用哪个对象要到函数被调用时才能确定,所以它的值在代码执行过程中会发生变化。

  • 在箭头函数中,this引用的是定义箭头函数的上下文,比如:
windows.color = 'green';
let o = {
    color: 'blue'
};
let showColor = () => console.log(this.color);
showColor();//输出 'green'
o.showColor = showColor;
o.showColor();//输出 'green'

可以看到两次调用,this引用的都是window对象,因为这个箭头函数是在window上下文中定义的。箭头函数中的this还会保留定义该函数时的上下文,所以在事件回调或者定时回调中调用某个函数时,想要保证this的指向正确就可以把回调函数写成箭头函数。例如:

function firstName(){
    this.name = 'Tom';
    setTimeout(() => console.log(this.name),1000);
}
function lastName(){
    this.name = 'Jack';
    setTimeout(function() { console.log(this.name);},1000);
}
new firstName();//输出 Tom
new lastName();//undefined

总结

静下心来读书吧,每次都会用新的收获!