0

我以两种方式调用 jQuery 函数,一种有效,另一种无效,因为this绑定不正确。

$('#my-div').fadeOut();

按预期工作,函数this内部的值fadeOut是 jQuery 对象。

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

不起作用,因为this现在的值是Window

这是两个例子的jsfiddle。

http://jsfiddle.net/XCAdP/

编辑:添加一些关于为什么我发布这个问题的说明,我真的不想知道如何解决这个问题。那不是问题。我想了解为什么会这样。

4

2 回答 2

2

Yes, when you get a method as a function reference, you disconnect it from the object. A function only works as a method when you call it in the context of an object, which is usually done with the . operator, e.g. obj.method().

If you call a function without the context of an object, it's called with the global scope as context, i.e. the window object. Example:

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)

If you want to make it work as a method, you have to call it with the object as context:

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

You can use the proxy method to make a function that calls the function with the correct context:

var obj = $('#my-div');
var fadeOutFn = $.proxy(obj.fadeOut, obj);
fadeOutFn();
于 2013-06-26T19:42:10.957 回答
2

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

尝试这个:

var fadeOutFn = $('#my-div').fadeOut;
fadeOutFn.call($('#my-div'));

或者只是这样做:

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

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

读取函数.bind

对于不受支持的浏览器,您可以将其添加到您的 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;
  };
}
于 2013-06-26T19:40:09.183 回答