jQuery.post回调函数在什么上下文中调用? [英] What context is the jQuery.post callback function invoked in?

查看:90
本文介绍了jQuery.post回调函数在什么上下文中调用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

举个例子:

$(".button").click(function() {

    $.post("commandrunner.php",
        {
            param1: 'value',
            param2: 'value2',
            param3: 'value3'
        },
        function(data, textStatus) {
            $(this).parent().after('<p>button clicked</p>');
        },
        "json"
    );

});

我运行了它,但是没有用.在理论化回调之前,我尝试了几件事,但并未在此特定的".button"上下文中调用该回调,因此$(this)是无用的.相反,它起作用了:

$(".button").click(function() {
    var thisButton = $(this);

    $.post("commandrunner.php",
        {
            param1: 'value',
            param2: 'value2',
            param3: 'value3'
        },
        function(data, textStatus) {
            thisButton.parent().after('<p>button clicked</p>')
        },
        "json"
    );

});

这感觉有点像骇客.这是获得对单击按钮的引用的正确方法吗?以及(或任何其他回调)调用的是什么上下文?

谢谢!

阿里

解决方案

您在这里注意到的是JavaScript闭包的工作方式.与其他OO语言一样,调用方法时,它具有"this",类似于Java的this或Ruby的self.但是,JavaScript this具有很强的延展性,并且jQuery在调用回调时利用该属性将其设置为有用的值.

对于事件,jQuery将this指针设置为指向将事件处理程序绑定到的元素.检查一下:

var hello = function() {
  console.log("Hello " + this);
});

如果您是来自OO的背景,那么您可能会困惑不解地看一下上面的代码片段:this指向什么.默认情况下,它将指向全局对象(浏览器中的窗口).但是您可以轻松地覆盖它:

hello.call("world") // will print "Hello world"

Call在this之后接受多个参数,这些参数作为参数传递.称为apply的类似方法,也将this作为第一个参数,但将参数数组作为第二个参数.

现在,如果我们再来看您的示例:

$(".button").click(function() {

    $.post("commandrunner.php",
        {
            param1: 'value',
            param2: 'value2',
            param3: 'value3'
        },
        function(data, textStatus) {
            $(this).parent().after('<p>button clicked</p>')
        },
        "json"
    );

});

这里的问题是,当jQuery再次调用该函数时,它没有使用相同的this来调用它.创建匿名函数时,它将保留同一作用域中的所有 local 变量,但不保留this变量,该变量由JavaScript本身设置(设置为全局对象)或在调用时被覆盖. /p>

因此,解决方案是在局部变量中存储指向this的指针,然后该变量可用于闭包.

如上所述,解决方案是:

$(".button").click(function() {
  var parent = $(this).parent();
  $.post("commandrunner.php",
    {
      param1: 'value',
      param2: 'value2',
      param3: 'value3'
    },
    function() {
      parent.after('<p>button clicked</p>')
    },
    "json"
  );
});

通常,当我存储本地变量时,我将存储最具体的一组元素,以使回调代码更简单.常见的jQuery习惯用法是var self = this,这也很好.

还请注意,JavaScript函数不会检查参数的数量,因此,如果您不使用,将参数保留为空是完全合法的.它们仍将传递,但是空参数列表将被忽略.

Lets say for example:

$(".button").click(function() {

    $.post("commandrunner.php",
        {
            param1: 'value',
            param2: 'value2',
            param3: 'value3'
        },
        function(data, textStatus) {
            $(this).parent().after('<p>button clicked</p>');
        },
        "json"
    );

});

I ran this and it didn't work. I tried a couple of things before I theorized the callback wasn't being invoked in the context of this particular ".button" and so $(this) was useless. This worked instead:

$(".button").click(function() {
    var thisButton = $(this);

    $.post("commandrunner.php",
        {
            param1: 'value',
            param2: 'value2',
            param3: 'value3'
        },
        function(data, textStatus) {
            thisButton.parent().after('<p>button clicked</p>')
        },
        "json"
    );

});

This feels like a bit of a hack. Is this the right way to get a reference to the clicked on button? And what context is that (or any other callback) invoked in?

Thanks!

Ali

解决方案

What you've noticed here is the way JavaScript closures work. As in other OO languages, when a method is invoked, it has a "this", which is similar to Java's this or Ruby's self. However, the JavaScript this is remarkably malleable, and jQuery takes advantage of that property to set it to a useful value when it calls your callback.

In the case of events, jQuery sets the this pointer to point at the element that you bound the event handler to. Check this out:

var hello = function() {
  console.log("Hello " + this);
});

If you come from an OO background, you might look at the above snippet in bewilderment: what does this point to. By default, it will point at the global object (window in browsers). But you can easily override that:

hello.call("world") // will print "Hello world"

Call takes multiple arguments after the this which are passed in as arguments. A similar method, called apply, will also take a this as the first argument, but takes an Array of arguments as the second parameter.

Now, if we look at your example again:

$(".button").click(function() {

    $.post("commandrunner.php",
        {
            param1: 'value',
            param2: 'value2',
            param3: 'value3'
        },
        function(data, textStatus) {
            $(this).parent().after('<p>button clicked</p>')
        },
        "json"
    );

});

The issue here is that when jQuery called the function again, it did not call it with the same this. When you create an anonymous function, it will hold onto all local variables in the same scope, but not this, which is set by JavaScript itself (to the global object) or overridden when called.

As a result, the solution is to store off a pointer to this in a local variable, which will then be available to the closure.

The solution, as mentioned above, is:

$(".button").click(function() {
  var parent = $(this).parent();
  $.post("commandrunner.php",
    {
      param1: 'value',
      param2: 'value2',
      param3: 'value3'
    },
    function() {
      parent.after('<p>button clicked</p>')
    },
    "json"
  );
});

In general, when I store off a local, I store off the most specific set of elements I can, to make the callback code simpler. The common jQuery idiom is to do var self = this, which is perfectly fine as well.

Also note that JavaScript functions do not check the number of parameters, so it's perfectly legal to leave the parameters empty if you do not use them. They will still be passed in, but the empty parameter list will simply be ignored.

这篇关于jQuery.post回调函数在什么上下文中调用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆