【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);
相关推荐
JieE2126 小时前
LeetCode 226. 翻转二叉树|JS 递归超详细拆解,二叉树入门经典题
javascript·算法
JieE2126 小时前
LeetCode 104. 二叉树的最大深度|递归思路超详细拆解
javascript·算法
kyriewen10 小时前
我用 AI 一周写完了整个项目,上线第一天就崩了——这是我踩过最贵的 5 个坑
前端·javascript·ai编程
Larcher10 小时前
AI Loop:让AI像人一样自主完成任务的核心机制
javascript·人工智能·设计模式
默_笙10 小时前
🃏 JS 只有 8 种数据类型,但我花了 2 天才搞懂 null 和 undefined 的区别
javascript
jump_jump11 小时前
流式 HTML:从 htmx 片段装配到浏览器原生增量渲染
javascript·性能优化·前端工程化
swipe13 小时前
正则表达式入门到进阶:从表单校验到手写模板引擎
前端·javascript·面试
kyriewen13 小时前
前端错误监控最全指南:捕获 JS 异常、Promise 拒绝、资源加载失败,附上报代码
前端·javascript·监控
大家的林语冰13 小时前
ESLint 近期动态大全,新版本正式发布,antfu 大佬推荐的插件也更新了!
前端·javascript·前端工程化
胡志辉15 小时前
深入浅出 call、apply、bind
前端·javascript·后端