JS中的this到底指的哪?

引言

this到底指的是哪,这个问题困扰了不少前端工程师。笔者在开发Vue项目的时候,时常因为this碰到各种奇奇怪怪的问题。今天笔者会通过本文细致的剖析this。

在全局中使用this

在浏览器中this指向的是window,大家可以自行测试。
在node环境中,this指向的是{} 。

函数中使用this

开发中,在函数里使用this

但是,开发中很少直接在全局作用于下去使用this,通常都是在函数中使用。所有的函数在被调用时,都会创建一个执行上下文,这个执行上下文中存放着函数的调用栈,AO对象等,(不了解这些概念的可以去看看笔者之前的文章)。this也是这些记录中的一个(执行上下文中也存放了this)。

函数里this到底指哪?

首先我们要明确一点,函数在调用时,javascript会默认给this绑定一个指。this的绑定和定义的位置(编写的位置)没有关系,并且this是在运行时被绑定的。
其次,this有四种绑定规则,它们分别是:默认绑定、隐式绑定、显示绑定、new绑定。笔者会在下文举例说明。

默认绑定

独立函数调用即为默认绑定,此时this打印的值为window。大家一定要注意我说的,this是在函数调用时被确定值的,与它定义的位置没有关系!!! 下面直接上代码。

function foo(){  //代码1 这很好理解
    console.log(this); //window
}

foo() //此处即为独立函数调用 

function foo(){
    console.log(this);  //window,它们都是一样的
}

let fn = foo()
fn()  
function test1(){  //代码2,这里打印的都是window
    console.log(this);
    test2()
}

function test2(){
    console.log(this);
    test3()
}

function test3(){
    console.log(this);
}

test1()
 


function foo(func){
    func()
}

let obj = {
    name : 'why',
    bar : function(){
        console.log(this);
    }
}

foo(obj.bar)  //这里也是this

隐式绑定

隐式绑定绑定需要有一个前提条件,必须在调用的对象内部有一个对函数的引用(比如一个属性),如果没有这样的引用,函数就会报错。通过这个引用,间接将this绑定到这个对象上了。

听起来很抽象,实际上就是你调用对象中的函数,对象里要有它。

比如下面这个代码

//案例1
function foo(){
    console.log(this);
}

var obj = {
    name : 'why',
    foo : foo
}

obj.foo() //obj对象

显示绑定

call, apply, bind函数可以制定this
所有的函数上都有call,apply与bind方法,它们可以用来调用函数,比如如下的代码,跟sum()一样。

但是它们可以指定this,具体如下面的代码,第一个参数就是设置this的指向。

call apply bind的区别

call与apply传参各有不同,apply需要传数组,它们都是没返回值的。
bind有返回值。

let obj = {
    name : 'harry',
    age:18
}

function sum(num1,num2){
    console.log(num1+num2,this); 
}

sum.call("aaa",20,30)  //call与apply是没有返回值的
sum.apply(obj,[20,30])
let fn = sum.bind("sdds",20,30)  //传参跟call一样
fn() //这里的this是sdds,显示绑定的优先级高于独立函数

new绑定

javascript中使用new关键字,函数可以当做一个类的构造函数来使用.

//使用new绑定  
//这个this是在调用这个构造器时创建出来的对象
function Person(name,age){
    this.name = name
    this.age = age

}

var p1 = new Person("why",18)
console.log(p1.name,p1.age);
var p2 = new Person("kobe",30)
console.log(p2.name,p2.age);

特殊函数的this

setTimeout

seTimeout实现的逻辑如下

function hySetTimeout(fn,duration){
    fn()  //内部类似这样调用的
}

hySetTimeout(function(){
    console.log(this);  //这里就是window
},3000)

JS的dom监听

html代码就省略了
addEventListner也是一样的

const boxDiv = document.querySelector('.box')
boxDiv.onclick = function(){
    console.log(this);  //那个dom

    //内部做了一个boxDiv.onclick()这个操作
    //bixDiv.onClick   
}

this绑定规则优先级

  • 默认绑定优先级最低
  • call/apply /bind这类显示绑定高于 隐式绑定
  • new绑定值最高

new > 显示 > 隐式 > 默认

箭头函数的this

箭头函数不使用this的四种规则,在箭头函数中压根就没有this这个东西。如果要找就是去外层作用域里找。

在开发中常见的一种情况(这个非常实用)

var obj = {
    data:[],
    getData:function(){
        // 发送网络请求
        setTimeout(function(){
            var result = ["1213","3224"];
            this.data = result;   //这里是不行的,这里this指向了window了
        },2000)
    }
}
obj.getData()

在箭头函数出现之前的解决方案(采用闭包解决):

var obj = {
    data:[],
    getData:function(){
        // 发送网络请求
        var _this = this
        setTimeout(function(){
            var result = ["1213","3224"];
            _this.data = result;   //箭头函数之前的解决方案
        },2000)
    }
}
obj.getData() //A处调用

箭头函数出现之后,就不用闭包这种解决方案了。因为箭头函数不绑定this,它会直接从上层作作用域里寻找,此时它找到了obj。(因为A处调用)

var obj = {
    data:[],
    getData:function(){
        // 发送网络请求
        setTimeout(()=>{
            var result = ["1213","3224"];
            this.data = result;   
        },2000)
    }
}

obj.getData()

转自本人掘金 https://juejin.cn/post/7105363028522041380/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值