在javascript对象文字符号声明中调用函数

Sha*_*aoz 18 javascript object-literal

我正在尝试使用this关键字调用我创建的对象文字中的函数.但是错误显示说this.doTheMove()不是功能:

window.onload = function(){

  var animBtn = document.getElementById('startAnim');

  animBtn.addEventListener('click', Animation.init, false);

}

var Animation = {
  init: function(){

     this.doTheMove(); // I'm calling the function here, but it gives an error.

  },
  doTheMove: function(){

    alert('Animation!');

  }
}
Run Code Online (Sandbox Code Playgroud)

为什么会出错?

Ray*_*nos 16

对正在发生的事情的解释.Pointy的答案很好,但我想更一般地解释它.this可以在这里找到一个非常好的研究

事件处理程序只是一个回调.你传递一个函数和一个事件来监听.它所做的一切就是调用该函数.

Animation.init只是该函数的一个getter.可以这样想:

var callback = Animation.init
animBtn.addEventListener('click', callback, false);
...
// internal browser event handler
handler() {
   // internal handler does stuff
   ...
   // Oh click event happened. Let's call that callback
   callback();
}
Run Code Online (Sandbox Code Playgroud)

所以你所做的就是传入

var callback = function(){
   this.doTheMove(); // I'm calling the function here, but it gives an error.
}
Run Code Online (Sandbox Code Playgroud)

默认情况下在javascript中this === window.如果没有设置为某个东西,这将引用全局对象.净效应是window.doTheMove被称为.而且这个功能不存在.

在这种情况下,由于callback事件处理程序会动态this调用node.doTheMove该对象,因此该对象指向触发该事件的DOM对象,因此您的调用仍然不存在.

你想要做的是用动画引用它.

var callback = function() {
    Animation.init();
}
Run Code Online (Sandbox Code Playgroud)

这是一个函数的执行,并执行initAnimation.当你在像这样的对象上执行它时,就像this === Animation你期望的那样在内部执行它.

总结一下.这里的问题是它Animation.init只是对函数的引用.它没有像Pointy提到的任何其他信息.

  • 你的答案大多是正确的(最终结果绝对正确).唯一的错误就是*"净效果就是那个窗口.调用了移动电话."*.因为`init`被传递给`addEventListener`,它实际上是从`animBtn`元素的上下文中调用的,所以`this.doTheMove()`实际上是`animBtn.doTheMove()`.同样,最终结果是一样的.只是一个小细节. (3认同)

Poi*_*nty 10

你必须改变你设置的方式:

window.onload = function(){

  var animBtn = document.getElementById('startAnim');

  animBtn.addEventListener('click', function() { Animation.init(); }, false);

}
Run Code Online (Sandbox Code Playgroud)

在JavaScript中,函数碰巧被定义为对象文字的一部分的事实实际上并不是非常重要(事实上,如果有的话).引用Animation.init 确实可以让你找到合适的函数,但问题是当稍后调用函数时(响应实际的"点击"),浏览器会调用函数但不知道对象"动画"应该是该this参考.同样,函数被声明为对象的一部分这一事实在这里根本不重要.因此,如果您想this成为您自己选择的特定内容,那么您必须确保在您控制的代码中明确设置它.上面的解决方案是关于最简单的方法:它使用匿名函数处理"click"事件,除了通过"Animation"通过显式引用调用"init"函数之外什么都不做.这将确保this在"init"运行时引用"Animation"对象.

另一种方法是使用某些浏览器和框架支持的".bind()"工具:

window.onload = function(){

  var animBtn = document.getElementById('startAnim');

  animBtn.addEventListener('click', Animation.init.bind(Animation); }, false);

}
Run Code Online (Sandbox Code Playgroud)

净效果几乎完全相同:对".bind()"的调用返回一个函数,该函数调用它所调用的函数(即"Animation"对象中的"init"函数),并且它的第一个参数作为this引用("context"对象).这与我们从第一个例子得到的相同,或者无论如何都是有效的.