关于JavaScript中的this

本文深入解析JavaScript中this关键字的工作原理及绑定规则,包括默认绑定、隐式绑定、显示绑定及new绑定等,帮助理解不同场景下this的具体行为。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

this到底是什么

作为类比,在C plus plus中,this的语意是代表本对象,在编写类代码时就已经绑定,必定是该类的一个实例,很明确。在js中,this也是代表着本对象。但是它与C++中不同的是,其是一个动态的概念,至于这个对象是“谁”,是在调用时决定的。

this是在运行时进行绑定的,并不是在编写时绑定,它的上下文取决与函数调用时的各种条件。this的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。

js中this实现的原理

当一个函数被调用时,会创建一个活动记录。这个记录会包含函数在哪里被调用(调用栈),函数调用方式,传入的参数信息。this就是这个记录的一个属性,会在函数执行的过程中用到。

判断this绑定的四条规则

默认绑定

默认绑定是this绑定到了全局对象,在独立函数调用时发生

function foo(){
    console.log(this.a);
}

var a = 2;

foo();//输出2,为全局作用域中的变量a。this此时绑定的全局作用域

隐式绑定

先看如下两段代码

function foo(){
    consloe.log(this.a);
}

var obj = {
    a:2,
    fun:foo
};


obj.fun(); //输出2
fucntion foo(){
    console.log(this.a);
}


var obj = {
    a:2,
    foo:foo
};

var bar = obj.foo;
var a = "oops global";
bar();//输出 oops global

上述的代码中,obj中的fun成员函数和变量bar都是对全局函数的foo的间接引用。两者调用的方式不同,分别是obj.fun()和bar()。但是输出的结果是不同的。对obj.fun()的this是绑定到了对象obj,而bar()this是绑定到全局对象。对obj.fun()来说,虽然obj对象只是间接引用函数foo,但是可以认为是函数被调用时obj对象拥有或包含了foo,所以this绑定到了对象obj。而对bar()只是函数间接引用的调用,跟直接调用foo本质是一样的,所以this绑定到是全局对象。

如下代码

function foo(){

    cosole.log(this.a);
}

function doFoo(fn){
    
    fn();
}

var obj = {
    a:2,
    foo:foo
};

var a = "oops,global";
doFoo(obj.foo);//输出 oops,global

在函数doFoo中对fn()的调用同foo()调用时一样的,fn只是函数foo的间接引用,this绑定到时全局对象。

显示绑定

使用Function的call,apply,bind方法可以将this绑定到指定对象。此后,this绑定不会再修改。

function foo(){
    consloe.log(this.a);
}

var obj = {
    a:2
};

var bar = function(){
    foo.call(obj); //将foo的this显示绑定到了obj对象
}

bar(); //输出2


被忽略的this

在显示绑定中,如果call,apply,bind函数传入的对象为null或undefined,那么这些值在调用时会被忽略,this直接绑定到全局对象。

function foo(){
    console.log(this.a);
}

var a = 2;
foo.call(null); //输出为2

这种方式有一个很常见的应用,可以用apply来展开一个数组,如下代码

function foo(a,b){
    console.log("a:"+a+",b:"+b);
}

foo.apply(null,[2,3]);

new绑定

new 来调用函数时会创建一个全新的对象,这个新对象会绑定到函数调用的this。

function foo(something){
    this.a = something;
}

var obj1 = {};
var bar = foo.bind(obj1);
//bar的this被显示绑定为obj1
bar(2);
console.log(obj1.a); //输出2

//通过new调用bar,将产生一个新的对象,this被绑定为新对象
var baz = new bar(3);
console.log(obj1.a); //输出2
console.log(baz.a); //输出3

bar被显示绑定到obj1上,但是new bar(3)并没有把obj1.a修改为3。相反,new修改了显示绑定调用bar()中的this。因为使用了new绑定,我们得到了一个名字为baz的新对象,并且baz.a的值是3。

判断this

  • 函数是否在new中调用(new 绑定)?如果是的话this绑定的新创建的对象。
var bar = new foo();
  • 函数是否通过call,apply(显示绑定)调用?如果是的话,this绑定的是指定的对象。
var bar = foo.call(obj2);
  • 函数是否在某个上下文对象中调用(隐式绑定)?如果是的话,this绑定的是那个上下文对象。
var bar = obj1.foo();
  • 如果都不是的话,使用默认绑定。如果在严格模式下,就绑定到undefined,否则绑定到全局对象。
var bar = foo();

以上。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mo4776

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值