专栏名称: SegmentFault思否
SegmentFault (www.sf.gg)开发者社区,是中国年轻开发者喜爱的极客社区,我们为开发者提供最纯粹的技术交流和分享平台。
目录
相关文章推荐
OSC开源社区  ·  RAG市场的2024:随需而变,从狂热到理性 ·  19 小时前  
程序猿  ·  41岁DeepMind天才科学家去世:长期受 ... ·  昨天  
OSC开源社区  ·  宇树王兴兴早年创业分享引围观 ·  3 天前  
OSC开源社区  ·  2024: 大模型背景下知识图谱的理性回归 ·  3 天前  
程序猿  ·  “未来 3 年内,Python 在 AI ... ·  4 天前  
51好读  ›  专栏  ›  SegmentFault思否

不要再问我 this 的指向问题了

SegmentFault思否  · 公众号  · 程序员  · 2019-01-11 08:00

正文

this的指向已经是一个老生常谈的问题,每逢面试都要去复习复习,近来巩固js的基础,决心彻底掌握这个知识点,一劳永逸。说明一下,为了不影响大家的思考过程,下面的代码都不会去注释答案,想知道答案,只需要去控制台执行一下。

四类场景逐一击破

首先,分析this的指向共有四种类型,在分析之前,我们首先带好两个锦囊:

1、函数 被调用时(即运行时) 才会确定该函数内this的指向。因为在函数中this与arguments是两个特殊的变量,在函数被调用时才会取得它们,而且搜索这两个变量时只会在活动对象范围里面去搜。(有关活动对象与变量对象的知识,请移步到js 中的活动对象 与 变量对象 什么区别?)

2、要确定函数中this的指向,必须先找到该函数被调用的位置。

认准第一种 test () 形式
  1. var a = 1

  2. function test () {

  3.    console.log(this.a)

  4. }

  5. test()

直接不带任何引用形式去调用函数,则this会指向全局对象,因为没有其他影响去改变this,this默认就是指向全局对象(浏览器是window,Node中是global)的。这个结论是在非严格模式的情况下,严格模式下这个this其实是undefined的。

认准第二种 xxx . test () 形式
  1. var a = 1

  2. function test () {

  3.    console.log(this.a)

  4. }

  5. var obj = {

  6.    a: 2,

  7.    test

  8. }

  9. obj.test()

这种形式对比起第一种,很明显 test () 已经是名花有主的了!看清楚,是谁呼唤的 test () ?没错,就是obj,所以this的指向就不言而喻了。一句话,谁去调用这个函数的,这个函数中的this就绑定到谁身上。

  1. var a = 1

  2. function test () {

  3.    console.log(this.a)

  4. }

  5. var obj = {

  6.    a: 2,

  7.    test

  8. }

  9. var obj0 = {

  10.    a: 3 ,

  11.    obj

  12. }

  13. obj0.obj.test()

即使是这种串串烧的形式,结果也是一样的, test () 中的this只对直属上司(直接调用者obj)负责。再来看一个综合点的例子:

  1. var a = 1

  2. function test () {

  3.    console.log(this.a)

  4. }

  5. var obj = {

  6.    a: 2,

  7.    test

  8. }

  9. var testCopy = obj.test

  10. testCopy()

嗯,聪明的你一定想到,换了个名字就能骗到我了!?虽然经过了一波改名换姓,但本质上还不是 obj . test () 嘛!结果一定和上面一样!唔,请F12在控制台试试,竟然……其实这里并不需要去思考什么,按照我们的套路,我们就认函数调时的样子,有没有看到最后调用的时候跟第一种情况一毛一样?我再介绍一个场景大家一定不会觉得陌生:

  1. var a = 1

  2. function test () {

  3.    console.log(this.a)

  4. }

  5. var obj = {

  6.    a: 2,

  7.    test

  8. }

  9. setTimeout(obj.test)

你可以意淫一下setTimeout的本质,是不是相当于有一个setTimeout函数,接收两个参数:

  1. function setTimeout (fn, time) {

  2.    // 这里干了一大波不可描述的事情,最后会去调一下你传进来的回调函数

  3.    fn()

  4. }

看到怎样调用你传进来的函数了吗!?再想想我们第一种形式的标题 认准第一种 test () 形式

认准第三种 test . call ( xxx ) / test . apply ( xxx ) / test . bind () 形式

看了上面两种形式之后,你可能会想,我非常讨厌上面那些矫情的扭扭捏捏的九曲十八弯的调用方式,让人毫无安全感,我要我自己指定this的指向,我要胜天半子!没问题,我的代码我做主:

  1. var a = 1

  2. function test () {

  3.    console.log(this.a)

  4. }

  5. var obj = {

  6.    a: 2,

  7.    test

  8. }

  9. var testCopy =







请到「今天看啥」查看全文