我这么跟你解释后,你还搞不this怎么指的,你找我…

我这么跟你解释后,你还搞不this怎么指的,你找我...

在JavaScript中,this的意思为“这个;当前”,是一个指针型变量,它动态指向当前函数的运行环境。在不同的场景中调用同一个函数,this的指向也可能会发生变化,但是它永远指向其所在函数的真实调用者;如果没有调用者,就指向全局对象window。

上面这段话只要记住一句:它永远指向其所在函数的真实调用者

那么我们来分析一下什么是真正的调用者,如下

function a() {
   console.log(this)
}

a()

我们学过执行上下文与作用域都明白一个点,这样定义的函数或者变量都会默认绑定到window上面去,那么上面那种调用还有一种方式就是,如下

function a() {
   console.log(this)
}

window.a()

同时两种函数执行后的打印结果,this都是指向window

接下来,我们再看一种情况。首先我们想象一下this一般在哪用的最多? 答案肯定是对象里面
所以我们来看一下 对象里面的this指向

var name = '大罗'
let obj = {
    name:'小罗',
    fn:function(){
        console.log(this.name) //  name是谁?
    }
}
obj.fn()

引用刚才我们说的:它永远指向其所在函数的真实调用者

我们怎么找到真实调用者这才是关键,很简单。我们看一下函数前面是谁呀。 fn函数前面是不是obj? 那么obj就是这个真实调用者

所以推断出obj == this是调用者,那么把函数里面this从脑海里面做一下隐式替换 不就相当于如下

var name = '大罗'
let obj = {
    name:'小罗',
    fn:function(){
        console.log(obj.name) //  隐式替换
        console.log(this.name) //  name是小罗
    }
}
obj.fn()

接下来我们再看一种情况,咱们把函数从对象上面提出来,如下

var name = '大罗'
function fn1(){
    console.log(this.name) //  name是谁?
}

let obj = {
    name:'小罗',
    fn:function(){
      fn1()
    }
}
obj.fn()

直接告诉大家结果,这里的this.name打印出来是大罗。 此时伙伴们就要问了,刚才还说最终调用者是看函数前面的东西。现在函数前面的东西没变。怎么结果就变了呢?

首先我们不要陷入思维误区,观察事情一定要仔细。

我们来看obj.fn()是一个定义好的函数。然后函数里面fn1()是一个函数调用哦,就是咱一开始就提取出去的函数嘛。。对吗?

那么看obj.fn()函数体里面的fn1()前面有东西调用它吗? 显然是没有,那么咱又回到一开始说的,如果函数前面没有东西调用,是不是默认就是window在调? 完整写法window.fn1() 如下

var name = '大罗'
function fn1(){
    console.log(this.name) //  name是谁?
}

let obj = {
    name:'小罗',
    fn:function(){
      window.fn1() //fn1()前面不加调用者,默认就是window
    }
}
obj.fn()

那这一切的一切就顺理成章的串起来,函数前面调用者是谁,this就指向谁。函数前面如果没有调用者,默认就指向window

好了想必大家心里都有一个底了。咱们直接上几道面试题,然后套用一下刚才的思想

1.第一道

const object = {
  message: 'Hello, World!',

  getMessage() {
    const message = 'Hello, Earth!';
    return this.message;
  }
};

console.log(object.getMessage()); // => ?

分析:啥都不说了,直接看函数前面是谁,最后结果就是谁。 打印出来肯定是:Hello, World!

2.第二道

var name = 'Bell'
function Pet(name) {
  this.name = name;

  this.getName = function a(){
      return this.name;
  } 
}

const cat = new Pet('Fluffy');

console.log(cat.getName()); // => ?

const { getName } = cat;
console.log(getName());     // =>?

分析:啥都不说了,直接看函数前面是谁,最后结果就是谁。第一个函数后面是cat,那么打印出来就是创建实例的时候传进去的值:“Fluffy”。 第二个函数前面什么都没有,那就默认window 打印出来就是 “Bell”

3.第三道


const object = {
  message: 'Hello, World!',

  logMessage() {
    console.log(this.message); // => ?
  }
};

setTimeout(object.logMessage, 1000);

分析:打印出来是undefined,首先我们要搞清楚这里object.logMessage只是取到了函数体,并没有真正的执行。执行一个函数后面一定是有双括号的。那么这里就相当于把函数体复制过来了,前面有东西调用它吗?显然没有,没有就是window调。 而此时window上面找不到message 那就是undefined呗

好接下来咱扩展一下。怎么让上面的函数打印出’Hello, World!’呢? 伙伴们思考30秒

刚才咱不是说了么。谁在函数前面,谁就是真实调用者。只要想办法让object在函数前面就行了,如下改造一下


const object = {
  message: 'Hello, World!',

  logMessage() {
    console.log(this.message); // => ?
  }
};

setTimeout(function(){
    object.logMessage() //给它包一层函数,然后在这个函数里面直接调用logMessage函数
}, 1000);

除了上面的方法,还可以通过 bind 强行改变this指向


const object = {
  message: 'Hello, World!',

  logMessage() {
    console.log(this.message); // => ?
  }
};

setTimeout(object.logMessage.bind(object), 1000);

关于bind,call,apply的介绍以及用法,伙伴们可以去参考其他博客,这里就不多赘述了。

好了文章写到这里我的分享就结束了。。大家对this有新的认知了吗? 评论区告诉我

原文链接:https://juejin.cn/post/7234059013271715897 作者:阳火锅

(0)
上一篇 2023年5月18日 上午10:51
下一篇 2023年5月18日 上午11:01

相关推荐

发表回复

登录后才能评论