【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);
相关推荐
默_笙2 小时前
🚓 分诊台与拆题术:让 RAG 学会判断和规划
前端·javascript
呃呃呃呃ex2 小时前
10. 现代前端工程化:ES6 React 项目实战与原理解析
前端·javascript
浪遏2 小时前
D2C 系统架构复盘:从设计稿到代码,我们踩过的坑和最终方案
前端·javascript·后端
Blanche15002 小时前
Webpack 构建流程解析
javascript·面试
Flynt2 小时前
官方说一个破折号拖慢整段高亮,我在 Node 里验证了一遍:机制是真的,2.8 倍没跑出来
javascript·性能优化·v8
默_笙2 小时前
🚗 把小说装进数据库了:我的第一个 RAG,和它的五个硬伤
前端·javascript
像我这样帅的人丶你还2 小时前
📱iPhone Duo 开屏动画咋实现的?
javascript·webgl·three.js
Leslie1652 小时前
把 SQL 性能诊断接入模型 API:从谓词分析到可验证优化
javascript
gnip2 小时前
UniApp 内嵌 H5 通信全攻略
前端·javascript
用户6802659051192 小时前
企业电脑统一管理怎么做?2026企业终端统一管理方法与工具推荐
javascript·后端·面试