我有以下Javascript类:
class App {
log_text(text) {
console.log(text)
}
process_response(response) {
this.log_text(response) // Uncaught TypeError: this.log_text is not a function
// self.log_text(response) // Uncaught TypeError: self.log_text is not a function
}
do_stuff() {
this.log_text('hello') // OK
}
fetch_data() {
jQuery.get('http://example.com/data/sample.txt', this.process_response, 'text')
}
}
调用方法do_stuff
时,我可以通过调用log_text
来访问this.log_text
。但是,在此示例中用作process_response
的回调处理程序的方法jQuery.get
失败了,因为this
在该上下文中表示完全不同的对象。
类似地,self.log_text
也会引发TypeError。
在此示例中,从log_text
调用process_response
的可能(或正确的)方法是什么?
答案 0 :(得分:3)
发生的事情是,您正在传递process_response函数,仅此而已,正如您所看到的那样,这些更改的上下文。一种解决方法是使用箭头语法将其包装,当jQuery触发回调时,它将保留此值。
fetch_data() {
jQuery.get('http://example.com/data/sample.txt', (r)=> this.process_response(r), 'text')
}
答案 1 :(得分:1)
您可以使用Function.bind()
来设置process_response
函数的上下文
fetch_data() {
jQuery.get('http://example.com/data/sample.txt', this.process_response.bind(this), 'text')
}
答案 2 :(得分:1)
您可以使用箭头功能,该功能具有词法this
-
fetch_data() {
jQuery.get
( 'http://example.com/data/sample.txt'
, r => this.process_response(r)
, 'text'
)
}
或使用Function#bind
将上下文(以及可选的一些参数)绑定到函数-
fetch_data() {
jQuery.get
( 'http://example.com/data/sample.txt'
, this.process_response.bind(this)
, 'text'
)
}
或者像历史上一样,用var保存上下文;现在,相对于上述技术而言,它已经不那么受欢迎了-
fetch_data() {
var ctx = this
jQuery.get
( 'http://example.com/data/sample.txt'
, function (r) { ctx.process_response(r) }
, 'text'
)
}
但是,新的JS功能将改善您的生活质量。考虑将您的 jqXHR 强制为 Promise ,以便您可以使用async
和await
-
const get = (opts = {}) =>
new Promise
( (resolve, reject) =>
$.get(opts)
.done((req, status, res) => resolve(res))
.fail((req, status, err) => reject(err))
)
结果是代码更加扁平,不再需要许多多余的功能,例如fetch_data
和process_response
。更好的是,我们的思想从绑定功能和动态上下文的思考中解放出来-
class App {
log_text(text) {
console.log(text)
}
async main () {
const res = await
get ({ url: '/data/sample.txt', dataType: 'text' })
this.log_text(res)
}
}
您甚至可以为get
包装器设置默认选项-
const defaultOpts =
{ dataType: 'text' }
const get = (opts = {}) =>
new Promise
( (resolve, reject) =>
$.get({ ...defaultOpts, ...opts })
.done((req, status, res) => resolve(res))
.fail((req, status, err) => reject(err))
)
然后使用它-
async main () {
const res = await
get ({ url: '/data/sample.txt' })
this.log_text(res)
// ...
}