夏天到了,了解一下JS的this指向问题

175 阅读4分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第5天,点击查看活动详情

javascript的this在工作编写业务的过程中十分常用,面试中也是一个屡见不鲜的面试题,今天我们就来详解一下this的指向问题,首先来了解一下什么叫做this

什么叫做this

自身执行上下文就做作this,准确来说,this是指当前函数运行环境的运行时自动生成的一个对象;

this并不是一成不变的,他会根据当前函数执行环境会做出相应不同的指向;

this的指向

this的运行环境有以下几种:

全局使用

在非严格模式和严格模式下,在全局环境下的this是都是指向顶级对象window,在全局环境下运行的函数也是指向的window

console.log('非严格下的this',this,this===window);
function fn(){
console.log('全局函数下执行的window',this,this===window);
}
fn();

使用"use strict"关键字即可开启严格模式

"use strict"
console.log('严格模式下的this',this,this===window);

不是说全局环境下的this都是指向window,为什么全局环境下运行的函数也是指向的window呢,不是应该指向当前的函数的,javascript是一个面向对象的编程语言,声明的函数或者变量没有指定属于那个对象,那么它就会属于顶级对象window

function fn(){
console.log('全局函数下执行的window',this,this===window);
}
fn();
//在全局环境下调用函数就相当于
window.fn();
//他们俩个运行的结果是一样的

普通对象

普通对象里面定义的函数指向的是自身,但是唯有一个函数例外,那就是箭头函数,箭头函数的this,JavaScript规定他没有this,它需要去捕获最近作用域的this,而普通函数的this,是谁调用它,它的this就指向谁

let obj = {
    name: '若水', age: '20岁', 
    help() {
        console.log('普通函数this', this, this == obj, this == window);
    }, artty: () => {
        console.log('箭头函数this', this, this == obj, this == window);
    }
}
obj.artty()
obj.help()

obj对象中并没有this,所以箭头函数会向最近作用域查找,obj对象调用者为window所以箭头函数打印为window

构造函数

当我们使用new 关键字对一个函数进行使用的时候,他就是构造函数,构造函数里面的this取决于构造函数的实例对象

function Structure(name, age) {
    this.name = name;
    this.age = age;
    this.point = function () {
        console.log('实例对象普通函数的this', this);
    }
    this.arrow = () => {
        console.log('实例对象箭头函数的this', this);
    }
}
let obj = new Structure('若水', '20岁');
console.log(obj.name);
obj.point();
obj.arrow();

这里我们会发现构造函数创建实例的时候,里面箭头函数的this不指向window了,而是和普通函数一样指向了构造函数的实例,这是因为箭头函数内部的this是捕获最近作用域的this,而构造函数通过new关键字使this指向了创建的实例对象,箭头函数是在构造函数里面定义的,所以在创建实例的时候,构造函数执行了,这时候箭头函数所在运行环境就是创造实例对象的环境,构造函数的this指向是由实例对象所定义的。所以箭头函数的this就会指向实例对象

改变this的方法

外层定义this

var name='前端'
let obj={
    name:'若水',
    fn(){
        let that=this;
        setTimeout(function(){
            console.log(this.name);
            console.log(that.name);
        },0)
    }
}

通过这样的操作可以使得内部可以使用外部的this,防止this指向错误

箭头函数的方法

我们可以利用箭头函数会寻找就近作用域的this,实现this指向的改变

var name='前端'
let obj={
    name:'若水',
    fn(){
        setTimeout(()=>{
            console.log(this.name);
            console.log(this.name);
        },0)
    }
}

call方法

call获得this指向后会立即执行,传递参数往后传就行了

function fn() {
    console.log(this.name);
}
let obj={name:'三千弱水'};
fn.call(obj);

apply方法

apply方法获得this指向后会立即执行,不过他接受的参数是一个数组

//定义一个数组使用apply方式获取最大值
let arr = [1, 66, 3, 99, 4];
//这里的Math.max方法不接受一个数组的数据,我们就要使用到这个方法
let max = Math.max.apply(null, arr);

bind方法

bind方法获取this后不会立即执行而是会返回一个改变this后的函数

function fn() {
    console.log(this.name);
}
let obj={name:'三千弱水'};
//因为有返回值,所以需要接受一下,然后调用函数就可以调用返回值
let f=fn.bind(obj);
f()

祝大家每天开开心心的,坚持努力,无惧未来!