起源
几天前在实现一段业务逻辑的时候,写了一段代码,大概就是封装了一个报告类,然后根据传入的参数不同,获取不同的报告。报告类代码如下(具体业务逻辑已经去掉,?的代码纯粹为了说明this指向问题而写)
class ReportServer {
getReport (reportType) {
// 统一的获取报告方法
return '获得'+ reportType +'报告'
}
getUserReport () {
// 各自的业务处理。。。
return this.getReport('用户')
}
getProductReport () {
// 各自的业务处理。。。
return this.getReport('产品')
}
getAreaReport () {
// 各自的业务处理。。。
return this.getReport('地域')
}
}
复制代码
调用代码
const reportType = 'user' // 传入的参数
const reportServer = new ReportServer()
const reportMap = {
'user': reportServer.getUserReport,
'product': reportServer.getProductReport,
'area': reportServer.getAreaReport
}
reportMap[reportType]()
复制代码
然后程序一运行,报了一个 TypeError: this.getReport is not a function 的错误。看到错误的第一秒,我的脑袋里闪过了我是谁?我在哪?我在干什么?下一秒:不可能!ReportServer这个类里面明明有getReport这个方法!
思考
言归正传,看到这个报错,第一反应就是this指向不对了,回忆了一下js中关于this的知识:
- 函数有所属对象,则指向所属对象
- 函数没有所属对象就指向全局对象
- 用new构造就指向新对象
- 通过 apply 或 call 或 bind 来改变 this 的所指。
没错,现在这个情况就是属于函数有所属对象,但是这个对象已经不在是reportServer,而是reportMap了,因为js中的this,是在函数真正执行的时候才会确认指向的。看看?的代码,更加强力的说明这一点
const reportMap = {
'user': reportServer.getUserReport,
'product': reportServer.getProductReport,
'area': reportServer.getAreaReport,
'test': 'test'
}
class ReportServer {
//...
getUserReport () {
// 各自的业务处理。。。
console.log(this)
return this.getReport('用户')
}
}
// 最后在执行时,这个this:
{
'user': [Function: getUserReport],
'product': [Function: getProductReport],
'area': [Function: getAreaReport],
'test': 'test'
}
复制代码
好吧,记得刚开始学习js的时候,还是有着重的去学习this这方面的知识,然而在实际开发中,还是会不经意的出错,幸好能第一时间反应过来Orz。
解决
好咯,既然是this指向问题,那么用call/apply指定正确的this:
reportMap[reportType].call(reportServer) // 输出:获得用户报告
复制代码
或者使用?方法
const reportMap = {
'user': 'getUserReport',
'product': 'getProductReport',
'area': 'getAreaReport'
}
reportServer[reportMap[reportType]]() // 输出:获得用户报告
复制代码
再或者,改写为if-else的形式,当然我最开始用hash的写法,就是不想写if-else (⊙﹏⊙)
Thanks!