第二——方法中的this值当你有一个对象,其有一个函数成员,冲父对象调用这方法,this的值将指向父对象 。例如:
var marty = {firstName: "Marty",lastName: "McFly",timeTravel: function(year) {console.log(this.firstName + " " + this.lastName + " is time traveling to " + year);}}marty.timeTravel(1955);// Marty McFly is time traveling to 1955
你可能已经知道你能引用marty对象的timeTravel方法并且创建一个其他对象的新引用 。这实际上是JavaScript非常强大的特色——使我们能够在不同的实例上引用行为(调用函数) 。
var doc = {firstName: "Emmett",lastName: "Brown",}doc.timeTravel = marty.timeTravel;
所以——如果我们调用doc.timeTravel(1885)将会发生什么?
doc.timeTravel(1885);// Emmett Brown is time traveling to 1885
再次——上演黑暗魔法 。嗯,并不是真的 。记住,当你调用一个方法的时候,this上下文是被调用函数父的父对象 。
当我们保存marty.TimeTravel方法的引用然后调用我们保存的引用时发生了什么?让我们看看:
var getBackInTime = marty.timeTravel;getBackInTime(2014);// undefined undefined is time traveling to 2014为什么是“undefined undefined”?!而不是“Matry McFly”?
让我们问一个关键的问题:当我们调用我们的getBackInTime函数时父对象/容器对象是什么?当getBackIntTime函数存在于window中时,我们调用它作为一个函数,而不是一个对象的方法 。当我们像这样调用一个函数——没有容器对象——this上下文将是全局对象 。David Shariff有一个伟大的描述关于这:
无论何时调用一个函数,我们必须立刻查看括号的左边 。如果在括号的左边存在一个引用,那么被传递个调用函数的this值确定为引用所属的对象,否则是全绝对象 。由于getBackInTime的this上下文是window——没有firstName和lastName属性——这解释了为什么我们看见“undefined undefined” 。
因此我们知道直接调用一个函数——没有容器对象——this上下文的结果是全局对象 。然而我也说我早就知道我们的getBackInTime函数存在于window上 。我是如何知道的?好的,不像上面我包裹getBackInTime在不同的上下文(我们探讨立即执行函数表达式的时候),我声明的任何变量都被添加的window 。来自Chrome控制台的验证:
文章插图
是时候讨论下this的主要用武之地之一了:订阅事件处理 。
第三(仅仅是#2的扩展)——异步调用方法中的this值所以,让我们假装我们想调用我们的marty.timeTravel方法当有人点击一个按钮时:
var flux = document.getElementById("flux-capacitor");flux.addEventListener("click", marty.timeTravel);
在上面的代码中,当用户点击按钮是,我们会看见“undefined undefined is time traveling to [object MouseEvent]” 。什么?好——首先,非常明显的问题是我们没有给我们的timeTravel方法提供year参数 。反而,我们直接订阅这方法作为事件处理程序,并且MouseEvent参数被作为第一个参数传递个事件处理程序 。这是很容易修复的,但真正的问题是我们再次见到“undefined undefined” 。不要无望——你已经知道为什么会发生这种情况(即使你还没意识到) 。让我们修改我们的timeTravel函数,输出this,从而帮助我们搞清事实:marty.timeTravel = function(year) {console.log(this.firstName + " " + this.lastName + " is time traveling to " + year);console.log(this);};
现在——当我们点击这按钮,我们将类似下面的输出 在你的浏览器控制台:文章插图
当方法被调用时,第二个console.log输出出this上下文——它实际上是我们订阅事件的按钮元素 。你感到吃惊吗?就像之前——当我们将marty.timeTravel赋值给getBackInTime变量时——对marty.timeTravel的引用被保存到事件处理程序,并被调用,但容器对象不再是marty对象 。在这种情况下,它将在按钮实例的点击事件中异步调用 。
所以——有可能将this设置为我们想要的结果吗?绝对可以!在这个例子里,解决方法非常简单 。不在事件处理程序中直接订阅marty.timeTravel,而是使用匿名函数作为事件处理程序,并在匿名函数中调用marty.timeTravel 。这也能修复year参数丢失的问题 。
推荐阅读
- 正确冲泡黄茶的七个步骤,冲泡蒙顶黄芽的禁忌
- 黄茶的作用和功效减肥助消化,普洱茶和皖西黄大茶功效与作用的区别
- BAT都在使用的开源接口管理平台
- 刀片服务器是什么?刀片服务器在哪些领域应用的较为广泛
- 遇事最有水平的三种处理方式
- 28个实用的穿搭小技巧,让你越穿越好看
- 香蕉苹果的七个错误防不胜防
- 保湿|10年没有换过的6款空瓶精华 好用的精华液推荐 有效的精华液排行榜
- 大黄茶的功效与作用,普洱茶和广东大叶青功效与作用的区别
- PS常用的快捷键,PS快捷键大全