【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);
相关推荐
集成显卡5 小时前
Rust实战七 |基于带 colored 颜色文字控制台的批量文件删除工具
开发语言·后端·rust
梦想的颜色5 小时前
TypeScript 完全指南(下):从类型体操到生产级配置
前端·javascript·typescript
比昨天多敲两行5 小时前
linux 线程概念与控制
java·开发语言·jvm
huaweichenai6 小时前
php 根据每个类型的抽签范围实现抽签功能
开发语言·php
codeejun7 小时前
每日一Go-73、云原生成本优化 —— 资源限制 & 指标驱动扩容
开发语言·云原生·golang
888CC++7 小时前
如何在 C 语言中进行程序调试?
前端·javascript·算法
就叫_这个吧7 小时前
Java注解、元注解、自定义注解定义及应用
java·开发语言·注解
Sam_Deep_Thinking8 小时前
聊聊Java中的of
java·开发语言·架构
kyriewen9 小时前
我招了一个“Prompt工程师”来写前端,结果项目差点崩了
前端·javascript·面试
小新11010 小时前
从零开始 Vue.js
前端·javascript·vue.js