理解 JS 回调函数中的 this
2017-09-26 16:29
183 查看
理解 JS 回调函数中的 this
任何变量或对象都有其赖以生存的上下文。如果简单地将对象理解为一段代码,那么对象处在不同的上下文,这段代码也会执行出不同的结果。例如,我们定义一个函数
getUrl和一个对象
pseudoWindow。
function getUrl() { console.log(this.document.URL); } var pseudoWindow = { document: { URL: "I'm fake URL" }, getUrl1: getUrl, getUrl2: function (callback) { callback(); this.func = callback; this.func(); } }
执行
getUrl(),打印出当前页面的
URL。
执行
pseudoWindow.getUrl1(),打印出
I'm fake URL。
执行
pseudoWindow.getUrl2(getUrl),先打印出当前页面
URL,后打印
I'm fake URL。
下面让我们用最简单粗暴的语言来解释以上代码。
概念
什么是 this?
this 就是函数调用使用的上下文。
什么是上下文?
上下文是在句号标记法中,句号前面的那个东西。例如
pseudoWindow.getUrl1,
pseudoWindow是
pseudoWindow.getUrl1()的上下文。
什么是自由变量?
当一个变量没有绑定到任何上下文时(或者说绑定到顶级作用域时,例如浏览器中的 window),它就是自由变量。
什么是变量与对象?
变量就是代码中你所用的标识符,一个标识符就是一个变量,多个变量可能指向同一个对象。例如:pseudoWindow.getUrl1 === getUrl // 得到 true
变量所处的上下文就是对象的作用域。
代码分解
调用 getUrl()
首先 getUrl函数是定义在全局环境中,它是一个自由变量,在浏览器中(以下描述均为浏览器环境)它的上下文就是
window,所以
window.getUrl()和
getUrl()是等价的。因此
this指向
window对象,打印出当前
URL。
调用 pseudoWindow.getUrl1()
首先 pseudoWindow是一个对象,它可以充当上下文角色。我们给它定义了一个属性
getUrl1,你可以将属性视为被绑定到某个上下文的变量,变量
getUrl1本身又指向了变量
getUrl所指向的对象,所以
pseudoWindow.getUrl1 === getUrl才会为
true。
当我们调用
pseudoWindow.getUrl1()时,它的意思是执行
getUrl()这段代码,执行代码所需的参数为空,上下文为
pseudoWindow。
所以函数中的
this指向了
pseudoWindow,而
pseudoWindow对象恰好又有
document属性,该属性恰好又有
URL属性,因此打印出
I'm fake URL。
调用 pseudoWindow.getUrl2(getUrl)
同理我们又定义了一个变量 getUrl2,并绑定到
pseudoWindow对象身上,使之成为后者的一个属性。而这个属性本身又指向一个匿名函数,我们姑且称之为
A,该函数对象接受另一个函数对象作为回调函数。
因此执行
pseudoWindow.getUrl2(getUrl)时,意思是执行代码
A,执行代码所需的参数为
getUrl这段代码,上下文为
pseudoWindow。
因此函数 A 中的
this指向了
pseudoWindow。
当程序执行到函数 A 内部的
callback()时,因为变量
callback没有绑定到任何上下文,因此它相当于一个自由变量,它的上下文就指向了
window对象,因此首先打印出当前页面的
URL。
接下来
this.func = callback意味着三件事:
我们新申明了一个变量
func。
通过
=操作符,我们将该变量指向了
callback所指向的函数对象。
通过
.操作符,我们将该变量绑定到了
this对象上,使之成为后者的一个属性,而本例中
this指向的就是
pseudoWindow对象。
于是当程序执行到
this.func()时,它的意思是执行
callback这段代码,执行代码所需的参数为空,上下文为
pseudoWindow。于是打印出了
I'm fake URL。
这段代码带来的一个副作用是我们隐式地为
pseudoWindow对象添加了一个新的属性
func,如果我们想要通过回调的方式打印出
pseudoWindow的
document.URL属性,又不想对
pseudoWindow对象造成任何影响,那么我们可以使用函数的
apply方法。所有函数都有
apply方法,它会将它接收的第一个参数设置为函数的上下文。
例如本例中我们可以改写代码成这样子:
var pseudoWindow = { document: { URL: "I'm fake URL" }, getUrl1: getUrl, getUrl2: function (callback) { callback(); callback.apply(this); } }
严格地说,你应该先检查 callback 参数类型是否是函数对象。
总结
Javascript 支持将函数作为参数传递,回调函数变量指向的函数对象都未与任何上下文绑定,所有未与明确上下文绑定的变量都是自由变量,浏览器器中所有自由变量的上下文都是 window 对象。
相关文章推荐
- 理解 JS 回调函数中的 this
- Js函数深入理解-闭包中的this
- 原生js模拟jQuery对象调用click事件来理解this和$(this)
- 对JS中global、window、document、this区别的理解
- js回调函数的理解
- 彻底理解js中this的指向
- js中this理解。
- 彻底理解js中this的指向
- js中this理解 --简单明了
- 图说js中的this——深入理解javascript中this指针
- [javascript]彻底理解 JS 中 this 的指向
- 彻底理解JS中This指向问题
- JS中this的理解
- js this理解
- js_this理解
- 彻底理解js中this的指向
- js中的回调函数的理解和使用方法
- 彻底理解js中this的指向!
- 如何理解js中的this和实际应用中需要避开哪些坑
- 彻底理解js中this的指向,不必硬背。