【JS】this指向

一、this指向的四种规则

1.默认绑定规则

对象指向,比较的是引用地址。

复制代码
console.log(this === window);      //true
console.log({} === {});     //false
//函数的独立调用
function test(){
    console.log(this === window);     //true
}
test();

2.隐式绑定规则

谁调用就指向谁。

复制代码
let a = 0;
let obj = {
    a:2,
    foo:function(){
        console.log(this) //obj
    }

}
obj.foo();

这里foo.function是obj对象里面的foo属性,是一个函数。当我们用对象的属性的方式调用这个方法的时候,那么this指向obj。

但如果foo写的是箭头函数,this就指向window了。

复制代码
let a = 0;
let obj = {
    a:2,
    foo:() => {
        console.log(this) //window or global object
    }

}
obj.foo();

那么下面两个this是否相同呢?

这两个this自然不是同一个this,因为不同函数执行产生不同的AO,所以每个函数有自己的this指向,但指向有可能相同(由当前执行方式决定)。

这里的相同说的是指向对象是同一个,但是他们的函数内部是不相等的,地址不同。

复制代码
let a = 0;
let obj = {
    a:2,
    foo:function(){
        console.log(this) //obj

        function test(){
            console.log(this); //window
        }
        test(); //独立调用就指向window
    }

}
obj.foo(); //这里是obj调用

下面这里立即执行我们要看执行环境,指向相应的全局对象。

这里立即执行函数全都指向window,因为这里是浏览器环境。

复制代码
let a = 0;
let obj = {
    a:2,
    foo:function(){
        console.log(this) //obj

        //立即执行函数全都指向window
        (function(){ 
            console.log(this); //window
        })()
    }

}
obj.foo();

闭包:闭包就是内层函数引用外层函数的变量。当函数调用的时候,导致内部新函数被定义,并抛出内部被定义的新函数。

作用:延长变量的声明周期。

复制代码
let a = 0;
let obj = {
    a:2,
    foo:function(){
        console.log(this) //obj
        function test(){
            console.log(this); //window
        }
        return test;
    }

}
obj.foo()(); //调用的时候依旧是独立调用相当于test()

隐式丢失

变量赋值

当方法被赋值的时候存在一种例外的现象,它调用了却没有指向它,管这种现象叫隐式丢失。其实本质还是看函数怎么执行的就可以了。也可以去看一下=赋值的原理。

我们知道this指向是在函数执行时产生的。而下面这段代码中是先将obj对象的属性赋值给b,然后再执行的。所以这里foo只是把只想空间的地址赋给b了,但是空间里的this指向没有任何改变。

复制代码
let a = 0;
function foo(){
    console.log(this)
}
let obj = {
    a:2,
    foo:foo
}
obj.foo();  //obj 对象调用
let b = obj.foo;
b();    //window 独立调用
let c = foo;
c();    //window 独立调用
foo();  //window 独立调用
参数赋值

函数传参过程就是变量赋值,应为js只有按值传递,那么这就也会考虑到隐式丢失的问题。

复制代码
let a = 0;
function foo(){
    console.log(this);
}
function b(x){
    x();    //window
}
let obj={
    a:2,
    foo:foo
}
//预编译的过程中,实参被赋值为形参。(值的拷贝的过程,浅拷贝)
b(obj.foo);

父函数有能力决定子函数的this指向。

new 把函数当做构造函数执行,this指向实例。

复制代码
let a = 0;
function foo(){
    console.log(this);
}
function b(x){
    x(obj); //window
    new x(); //强行指向实例之后的对象foo
    x.bind(obj)(); //强行指向obj
}

//api 接口中指明的

//回调函数:父函数,子函数
var arr = [1,2,3];
arr.forEach(function(item, idx, arr){
    console.log(this); //window
},this)
arr.sort(function(a, b){
    console.log(this); //window
    return a-b;
})
setInterval(function(){
    console.log(this); //window
})

let obj={
    a:2,
    foo:foo
}
//预编译的过程中,实参被赋值为形参。(值的拷贝的过程,浅拷贝)
b(obj.foo);
相关推荐
星夜离尘567 小时前
MATLAB 工程实验:不等间隔流量积分,先把缺口与覆盖率说清楚
开发语言·matlab·时间戳·数据质量·数值积分
Ai-_Man7 小时前
Meta Muse还是不可以导出左侧所有对话,只能点进去单条内容导出,方法不对吗?
开发语言·人工智能·ai·小程序·c#·1024程序员节
梓豪csd7 小时前
消息订阅中心:谁该收到哪条通知
java·开发语言·人工智能·低代码·自动化·1024程序员节
学逆向的8 小时前
C 枚举变量
c语言·开发语言·网络安全
Sakura_j_h_8 小时前
Python 在定时任务里输出 emoji,UnicodeEncodeError 从哪来
开发语言·字符编码·windows·python·定时任务
paopaokaka_luck10 小时前
宠物门店经营管理系统(销售与库存联动、进货自动记账、 退换与退款关联、员工个人业绩、ECharts 经营分析、滞销识别与客户分层、宠物档案年龄计算)
前端·javascript·spring boot·mysql·echarts·mybatis·1024程序员节
小成2023032026513 小时前
C++~07补充
开发语言·c++
鶴哥只手遮天14 小时前
jQuery 4.0 源码架构与工程实践-第 10 章 尺寸、几何与显隐
前端·javascript·jquery
2401_8858850416 小时前
国际语音C#接口怎么写?.NET环境下实现国际语音验证码批量下发
开发语言·c#·.net