浅说一下JavaScript中Class类的this指向问题

普通函数中this

普通函数内部的this对象指向的是在函数执行时绑定的对象,也就是说函数创建的时候是没办法确定这个this到底指向的是谁的

function fn() {
	console.log(this) // 创建时this没有指向性
}

fn() // 执行时才确定this指向,因为是在window环境下执行的所以指向window对象

var obj = {}
obj.f = fn
obj.f() // 执行时确定this对象,指向绑定的obj对象

document.onclick = fn // 绑定时确定this对象,指向触发该事件的document对象
document.onclick = function() {
  let fn = function() {
    console.log(this)
  }
  fn() // window
}

箭头函数中this

箭头函数的this在函数创建期间就绑定好了,它的this指向创建该函数所在的作用域对象

let fn = () => {
	console.log(this) // 确定this,指向fn所在的作用域,也就是window
}
fn() // this指向window
document.onclick = fn // this依旧指向fn声明时候所在的作用域window
document.onclick = function() {
  let fn = () => {
    console.log(this)
  }
  fn() // document
}

总结:不能通过call apply bind 去改变箭头函数其内部的 this 指向

class(类)中的this

类中的方法内部如果含有this,它默认指向类的实例,但是一旦单独使用,很可能报错

class Logger {
  printName(name = 'there') {
    this.print(`Hello ${name}`);
  }

  print(text) {
    console.log(text);
  }
}

const logger = new Logger();
const { printName } = logger;
printName(); // TypeError: Cannot read property 'print' of undefined

因为 printName 方法中的 this, 默认指向 Logger 类的实例,但是如果将这个方法提取出来单独使用,this 就会指向该方法运行时所在的环境,从而导致找不到 print 方法而报错

应用对比

let lis = document.querySelectorAll('li')
for(let i = 0; i < lis.length; i++) {
  lis[i].onclick = function() {
    let fn = function() {
      this.style.background = 'red'
    }
    setTimeout(fn, 1000)
  }
}

此时会报错Cannot set property 'background' of undefined
因为setTimeoutwindow的方法,所以这里其实是简写window.setTimeout的写法,也就是说此时setTimeout里面的函数fn中的this指向的其实是window这个对象,我们没办法对window对象设置背景色,所有才会报错,其实我们想要的是希望这里的this指向我们的绑定元素li,那我们可以使用箭头函数这样写

let lis = document.querySelectorAll('li')
for(let i = 0; i < lis.length; i++) {
  lis[i].onclick = function() { // function是普通函数,调用时候就是li click的时候所以this就是li
    let fn = () => { // 定义箭头函数时这个作用域中的this就是li
      this.style.background = 'red'
    }
    setTimeout(fn, 1000)
  }
}

此时fn中的this指向的就是其创建时的作用域,也就是lis[i]这个元素对象
这里onclick绑定的函数就不能用箭头函数了,否则就没办法将其this保留住了,所以一般事件函数我们都不要用箭头函数,否则函数中的this就没办法绑定这个事件元素对象了
如果我们将事件绑定定义的函数也用箭头函数,此时的 this 又会发生变化

let lis = document.querySelectorAll('li')
for(let i = 0; i < lis.length; i++) {
  lis[i].onclick = () => { // 箭头函数定义是在window环境下,所以this就是window
    let fn = () => { // 定义箭头函数时这个作用域中的this就是window
      this.style.background = 'red'
    }
    setTimeout(fn, 1000)
  }
}

原文链接:https://www.csdn.net/tags/Mtjacg0sMDQ5OTktYmxvZwO0O0OO0O0O.html#this_3

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值