Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/427.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript回调作用域_Javascript_Events_Binding_Scope_Callback - Fatal编程技术网

JavaScript回调作用域

JavaScript回调作用域,javascript,events,binding,scope,callback,Javascript,Events,Binding,Scope,Callback,我在回调函数中引用我的对象时遇到了一些普通的老JavaScript(没有框架)问题 function foo(id) { this.dom = document.getElementById(id); this.bar = 5; var self = this; this.dom.addEventListener("click", self.onclick, false); } foo.prototype = { onclick : function()

我在回调函数中引用我的对象时遇到了一些普通的老JavaScript(没有框架)问题

function foo(id) {
    this.dom = document.getElementById(id);
    this.bar = 5;
    var self = this;
    this.dom.addEventListener("click", self.onclick, false);
}

foo.prototype = {
    onclick : function() {
        this.bar = 7;
    }
};
现在,当我创建一个新对象时(在加载DOM之后,使用span#test)

onclick函数中的“this”指向span#test,而不是foo对象


如何在onclick函数中获取对我的foo对象的引用?

这是JS中最容易混淆的一点:“this”变量表示最局部的对象。。。但是函数也是对象,所以“this”指向这里。还有其他一些微妙之处,但我记不清了

this.dom.addEventListener("click", function(event) {
    self.onclick(event)
}, false);
我通常避免使用“this”,只需定义一个本地“me”变量并使用它即可。

(摘录了一些隐藏在其他答案注释中的解释)

问题在于以下几行:

this.dom.addEventListener("click", self.onclick, false);
在这里,您传递一个要用作回调的函数对象。当事件触发时,函数被调用,但现在它与任何对象都没有关联(此)

问题可以通过将函数(使用其对象引用)包装在闭包中来解决,如下所示:

this.dom.addEventListener(
  "click",
  function(event) {self.onclick(event)},
  false);
因为变量self在创建闭包时被赋值,所以闭包函数在以后调用时会记住self变量的值

解决此问题的另一种方法是创建一个实用函数(并避免使用变量绑定此函数):

更新后的代码如下所示:

this.dom.addEventListener("click", bind(this, this.onclick), false);

是ECMAScript 5的一部分,提供相同的功能。因此,您可以:

this.dom.addEventListener("click", this.onclick.bind(this), false);
对于尚不支持ES5的浏览器,请执行以下操作:


解释是,
self.onclick
在JavaScript中的含义与您认为的不同。它实际上意味着对象原型中的
onclick
函数
self
(不以任何方式引用
self
本身)

JavaScript只有函数,没有像C#这样的委托,因此不可能将方法及其应用对象作为回调传递

在回调中调用方法的唯一方法是在回调函数中自己调用它。因为JavaScript函数是闭包,所以它们能够访问在创建它们的作用域中声明的变量

var obj = ...;
function callback(){ return obj.method() };
something.bind(callback);
我写了这个插件

我想这会有用的


这个问题的一个很好的解释是(到目前为止,我在理解所描述的解决方案时遇到了一些问题)。

对于想要解决这个问题的jQuery用户,您应该使用谢谢,但是您能解释一下为什么我需要在那里创建一个匿名函数吗?为什么会改变绑定?每当触发事件时,“this”指的是调用该事件的对象。当您在问题中使用表单时,self.onclick只是一个匿名函数,在处理该函数时,它的工作方式就像您将其直接附加到span一样。当你把它包装在一个闭包中时,self.onclick(event)真的会做你想做的事情,例如,在定义闭包的上下文中使用“self”。这只对一个正在创建的对象有效;考虑<代码>函数(){VARI i的输出;(i=0;II返回)-在每次调用时创建一个新的<代码> var自/<代码>,它不像我前面的注释中的示例那样改变。(也有一个打印错误,应该从<代码>函数f-()/代码>开始)我调用了原型函数“onclick”以便轻松地将其关联起来。我知道它不会被实际的DOM onclick事件自动调用,这就是为什么我尝试使用事件侦听器将对象的onclick与DOM的onclick函数绑定。这不是我的观点,我理解您的onclick函数。我的观点是o self.onclick和foo.prototype.onclick之间的JavaScript差异。JavaScript中没有办法说“此方法绑定到此对象”。唯一的方法是使用closure.closure()可能是一个更好的名称。当您使用多个对象时,闭包将不起作用;您将始终引用创建的最后一个对象。实用程序函数起作用,因为每次都新存储参数。您的语句完全不准确。函数的apply()和call()方法允许您执行一个函数,其中“this”指的是您在调用中传递的变量。@Kenaniah:……因此,更令人困惑的是,代码的确切含义取决于它的调用方式!函数在JavaScript中非常灵活,不使用
this
很难解决问题。
this
是唯一的解决方案JS中的namic作用域功能,它为语言增加了很多功能。是的,函数是JS中的一级对象这一事实暗示了“执行上下文指针”的动态性质。如果使用得当,这是一个很好的功能。保存引用:
this.cb=this.onclick.bind(this);addEventListener(“单击”,this.cb);
this.dom.addEventListener("click", this.onclick.bind(this), false);
if (!Function.prototype.bind) {  
  Function.prototype.bind = function (oThis) {  
    if (typeof this !== "function") {  
      // closest thing possible to the ECMAScript 5 internal IsCallable function  
      throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");  
    }  

    var aArgs = Array.prototype.slice.call(arguments, 1),   
        fToBind = this,   
        fNOP = function () {},  
        fBound = function () {  
          return fToBind.apply(this instanceof fNOP  
                                 ? this  
                                 : oThis || window,  
                               aArgs.concat(Array.prototype.slice.call(arguments)));  
        };  

    fNOP.prototype = this.prototype;  
    fBound.prototype = new fNOP();  

    return fBound;  
  };  
} 
var obj = ...;
function callback(){ return obj.method() };
something.bind(callback);