JavaScript 中 this 指向问题

this 概览

  • this 在 js 中是一个内置指针变量,通常指向当前函数的调用对象

  • 当不存在显式调用者的情况一般默认指向全局对象 window

  • 箭头函数的 this 指向该函数所在的作用域指向的对象

一、全局作用域内的 this 指向

在全局作用域下,this始终指向全局对象window,无论是否是严格模式!
console.log(this); // 输出 window
window.console.log(this); // 输出 window

在全局作用域下,当没有显式调用的函数隐式被 window 调用,由于 this 指向函数的直接调用者,此时 this 指向全局对象 window

二、函数作用域内的 this 指向

函数内的 this 指向分为两种:非严格模式和严格模式

// 非严格模式
(function fn() {
    console.log(this); // 输出 window
}())

// 严格模式
(function fn() {
    'use strict'
    console.log(this); // 输出 undefined
}())
  • 非严格模式下函数作用域内因找不到当前显式调用者则隐式绑定到全局对象 window

  • 严格模式下函数作用域内找不到显式调用者时无法获取到外部对象,此时 this 为 undefined

三、对象作用域内的 this 指向

对象内部方法的this指向调用这些方法的对象,也就是谁调用就指向谁

对象作用域内的 this 指向也分两种情况:普通对象和嵌套对象

let a = {
    fn: function () {
        console.log(this);
    },
    b: {
        fnf: function () {
            console.log(this);
        }
    }
}

// 普通对象
a.fn();    // 输出对象 a
a['fn'](); // 输出对象 a
// 嵌套对象
a.b.fnf(); // 输出对象 b
a['b']['fnf'](); // 输出对象 b

可以看出,对象作用域内因为需要使用 . 或 [ ] 操作符访问对象内成员,因此具有显式调用的情况。此时,this 指向为直接调用的对象,若有嵌套情况,仍指向调用该函数的对象

特殊情况

当调用的函数返回值仍是个函数时,其内部 this 指向为 window,若开启严格模式,则为 undefined

let c = {
    d: function () {
        return function () {
            console.log(this);
        }
    }
}

c.d()(); // 输出对象 window

let c = {
    d: function () {
        'use strict'
        return function () {
            console.log(this);
        }
    }
}
c.d()(); // 输出 undefined

'use strict' 放置位置不影响输出结果

此种情况是因为函数内部形成了闭包,导致对象 c 调用属性名为 d 的函数时返回的函数调用暴露在全局作用域内,此时由函数 d 返回的函数调用则遵循全局 this 指向原则

四、箭头函数的 this 指向

箭头函数的this指向函数作用域所用的对象

由于箭头函数不能绑定 this,因此严格意义上来说箭头函数没有自己的 this 指针,准确来说是没有指向的对象。其 this 指针在被定义时会捕获外层执行环境,并将自身的 this 指向外层 this,当完成初始化后便无法更改定义后的箭头函数的 this 指向,包括 call、apply、bind等方法

let a = {
    fn: function () {
        console.log(this);
        return () => {
            console.log(this);
        }
    },
    b: {
        fnf: () => {
            console.log(this);
            return () => {
                console.log(this);
            }
        }
    }
}

a.b.fn()(); // 输出对象 a
a.b.fnf()(); // 输出对象 window

第一个箭头函数其定义在 fn 这个函数内,而 fn 函数内的 this 指向对象 a,则箭头函数内的 this 最终指向对象 a。第二个箭头函数定义在另一个箭头函数内,由于箭头函数 this 指针会指向最外层对象,则通常为全局对象window

五、构造函数内的 this 指向

构造函数内的this指向为与构造函数同名的实例
function Fn(...args) {
    console.log(this) // 输出 Fn {}
    this.id = args[0];
    this.userName = args[1];
    this.password = args[args.length - 1];
    console.log(this);
}

new Fn('000123', 'lily', '123456'); // 输出 Fn {id: '000123', userName: 'lil                                                            y', password: '123456'}

构造函数内this会指向即将返回的实例,从而我们得以使用this指针来初始化实例

六、原型链中的this

this在一个继承机制中,仍是指向它原本属于的对象,而不是从原型链上找到它时所属于的对象
let obj = {
    fn: function () {
        console.log(this);
    }
}

let obj_extend = {
    fnf: function () {
        console.log(this);
    }
};
obj_extend.__proto__ = obj;
console.log(obj_extend);    // 输出对象 obj_extend

这个例子中,将 obj_extend 的原型修改为 obj,由此继承了 obj 上的 fn 方法,通过输出对象可以看出,此时 fn 函数原本指向 obj 的this指向了obj_extend。由于直接调用 fn 函数的是 obj_extend,且发生了赋值操作,this 绑定隐式丢失,因此fn函数内的this指向其直接调用者

七、总结

本文整理了常见情况下的 this 指向问题,介于问题的复杂性,考虑对主动修改this的方法,如:call、apply、bind方法暂未涉及,详情可参考 CSDN上其他博主的博客

理解this指向有助于更好的帮助我们在日常开发过程中更好的灵活使用,提高我们的开发效率。同时也间接提高了js编码水平,从这些方面来说,这个知识点的重要性还是比较高的

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值