Javascript 如果从存储的变量调用jquery函数,则绑定不正确

Javascript 如果从存储的变量调用jquery函数,则绑定不正确,javascript,jquery,closures,this,Javascript,Jquery,Closures,This,我用两种方法调用jQuery函数,一种有效,另一种无效,因为这的绑定不正确 $('#我的div').fadeOut() 正如预期的那样工作,fadeOut函数中的this的值是jQuery对象 var fadeOutFn = $('#my-div').fadeOut; fadeOutFn(); 由于此的值现在是窗口 下面是两个示例的JSFIDLE 编辑:添加一些关于我为什么发布这个问题的澄清,我真的不想知道如何解决这个问题。这不是问题所在。我想了解它发生的原因。是的,它不知道它正在应用fad

我用两种方法调用jQuery函数,一种有效,另一种无效,因为
的绑定不正确

$('#我的div').fadeOut()

正如预期的那样工作,
fadeOut
函数中的
this
的值是jQuery对象

var fadeOutFn = $('#my-div').fadeOut;
fadeOutFn();
由于
的值现在是
窗口

下面是两个示例的JSFIDLE


编辑:添加一些关于我为什么发布这个问题的澄清,我真的不想知道如何解决这个问题。这不是问题所在。我想了解它发生的原因。

是的,它不知道它正在应用
fadeOut
动画的元素,并且
在这种情况下,
上下文主要是窗口,而不是jquery对象。您可以使用
函数传递上下文。调用

试试这个:

var fadeOutFn = $('#my-div').fadeOut;
fadeOutFn.call($('#my-div'));
或者干脆这样做:

使用function.bind将上下文绑定到函数引用,并调用它

var fadeOutFn = $().fadeOut.bind($('#my-div'));
fadeOutFn();
阅读

对于不受支持的浏览器,您可以将其添加到js文件中以获得支持,如文档中所述:

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 && oThis
                                 ? this
                                 : oThis,
                               aArgs.concat(Array.prototype.slice.call(arguments)));
        };

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

    return fBound;
  };
}

是的,它不知道它正在应用
fadeOut
动画的元素,并且
在这种情况下,这个
上下文主要是窗口,而不是jquery对象。您可以使用
函数传递上下文。调用

试试这个:

var fadeOutFn = $('#my-div').fadeOut;
fadeOutFn.call($('#my-div'));
或者干脆这样做:

使用function.bind将上下文绑定到函数引用,并调用它

var fadeOutFn = $().fadeOut.bind($('#my-div'));
fadeOutFn();
阅读

对于不受支持的浏览器,您可以将其添加到js文件中以获得支持,如文档中所述:

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 && oThis
                                 ? this
                                 : oThis,
                               aArgs.concat(Array.prototype.slice.call(arguments)));
        };

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

    return fBound;
  };
}

是的,当您获得一个方法作为函数引用时,您将其与对象断开连接。函数仅在对象上下文中调用时作为方法使用,这通常是通过
操作符完成的,例如
obj.method()

如果在没有对象上下文的情况下调用函数,则会以全局范围作为上下文调用它,即
窗口
对象。例如:

var obj = {
  name: "obj",
  method: function() { alert(this.name); }
};

obj.method(); // shows the name "obj"
var m = obj.method;
m(); // shows the name of window
m.call(obj); // shows the name "obj"

var obj2 = {
  name: "obj2"
};
m.call(obj2); // shows the name "obj2" (using the method from obj)
如果要使其作为方法工作,则必须使用对象作为上下文调用它:

var obj = $('#my-div');
var fadeOutFn = obj.fadeOut;
fadeOutFn.call(obj);
您可以使用创建一个函数,该函数使用正确的上下文调用该函数:

var obj = $('#my-div');
var fadeOutFn = $.proxy(obj.fadeOut, obj);
fadeOutFn();

是的,当您获得一个方法作为函数引用时,您将其与对象断开连接。函数仅在对象上下文中调用时作为方法使用,这通常是通过
操作符完成的,例如
obj.method()

如果在没有对象上下文的情况下调用函数,则会以全局范围作为上下文调用它,即
窗口
对象。例如:

var obj = {
  name: "obj",
  method: function() { alert(this.name); }
};

obj.method(); // shows the name "obj"
var m = obj.method;
m(); // shows the name of window
m.call(obj); // shows the name "obj"

var obj2 = {
  name: "obj2"
};
m.call(obj2); // shows the name "obj2" (using the method from obj)
如果要使其作为方法工作,则必须使用对象作为上下文调用它:

var obj = $('#my-div');
var fadeOutFn = obj.fadeOut;
fadeOutFn.call(obj);
您可以使用创建一个函数,该函数使用正确的上下文调用该函数:

var obj = $('#my-div');
var fadeOutFn = $.proxy(obj.fadeOut, obj);
fadeOutFn();

我认为关键是调用时不必重复
#my div
。@Barmar第二个如何使用bind。在这种情况下就不会重复了。
bind
mehod在一些稍旧的浏览器中不起作用,比如IE8。请改用
jQuery.proxy
方法。@PSL:既然已经包含jQuery,为什么还要添加另一个库?它不是库。。只是本机javascript ecmascript标准。但我不知道jquery是否已经包含了它…:)但你的解决方案也很好。我总是忘记$。Proxy我想关键是调用它时不必重复
#我的div
。@Barmar第二个如何使用bind。在这种情况下就不会重复了。
bind
mehod在一些稍旧的浏览器中不起作用,比如IE8。请改用
jQuery.proxy
方法。@PSL:既然已经包含jQuery,为什么还要添加另一个库?它不是库。。只是本机javascript ecmascript标准。但我不知道jquery是否已经包含了它…:)但你的解决方案也很好。对于$.proxy,我总是忘记$.proxyMy+1。我总是忘记这件事。但是我认为我们可以避免对象的消失。我对这个问题补充了一些解释。我不是在寻找解决方法,我只是想了解它发生的原因以及如何解释。@Keivan:我添加了一个更具描述性的解释来解释原因。My+1代表$.proxy。我总是忘记这件事。但是我认为我们可以避免对象的消失。我对这个问题补充了一些解释。我不是在寻找解决办法,我只是想了解为什么会发生这种情况以及如何解释。@Keivan:我为原因添加了更具描述性的解释。