在JS / jQuery代码中确定'this'指的是什么

时间:2014-02-02 00:58:05

标签: javascript jquery this asynccallback

在以下代码的多个实例中,我很难弄清楚'this'指的是什么:

 jQuery(function ($) {

    var coreChat = {

      fetch: function (fn) {
        $.ajax({
          url: "https://api.parse.com/1/classes/chats",
          data: {
             order: 'createdAt',
             limit: 10
          },
          type: "GET"
        })
        .done(function(data) {
          var messages = [];
          for (var i = 0, len = data.results.length; i < len; i++) {
            messages.push(data.results[i].text);
          }

          return fn(messages);
        });
      },

      send: function (message) {
        var data = JSON.stringify({text: message});
        $.ajax({
          url: "https://api.parse.com/1/classes/chats",
          data: data,
          type: "POST"
        });
      },

      display: function (messages) {

        // http://jsperf.com/update-only-text-vs-remove-dom

        var messageNode = $(".messages").find("li");

        messageNode.each(function (i) {
          var $this = $(this);
          if ($this.text() !== messages[i]) {
            $this.text(messages[i]);
          }
        });

      }

    };


    var myChat = {

      init: function () {
        **this**.fetchInitialData();
        **this**.bindSendEvent();
        **this**.refresh();
      },

      fetchInitialData: function () {
        var messagesWrapper = $(".messages");
        for (var i = 0; i < 10; i++) {
          $("<li></li>").appendTo(messagesWrapper);
        }
        myChat.updateMessages();
      },

      bindSendEvent: function () {
        $(".send").on("click", function (e) {
          var input = $(".draft");
          myChat.send(Chat.username + ": " + input.val());
          input.val("");
          e.preventDefault();
        });
      },

      refresh: function () {
        setInterval(function () {
          myChat.updateMessages();
        }, 3000);
      },

      updateMessages: function () {
        this.fetch(function (messages) {
          myChat.display(messages);
        });
      }

    };

    $.extend(myChat, coreChat);
    myChat.init();

  });

更具体地说,在代码的下半部分 - 在myChat对象中,有一个“init”属性,作为一个值,包含一个函数...

var myChat = {

      init: function () {
        this.fetchInitialData();
        this.bindSendEvent();
        this.refresh();
      },

这里指的是什么?并且coreChat在代码的第2行到最后一行被扩展到myChat的事实是否会对确定“this”指的是什么产生影响?

$.extend(myChat, coreChat);

此外,myChat对象的updateMessages属性中还有另一个'this'...

updateMessages: function () {
        this.fetch(function (messages) {
          myChat.display(messages);
        });
      }

^在这个例子中这是指什么? coreChat的fetch函数正在'this'上执行,但同样,'this'是什么?

作为一个快速切向问题 - 在updateMessages函数中,它调用'fetch'函数.'fetch'与回调函数异步('fetch'最初在coreChat对象中找到)。但是在updateMessages中,作为fetch参数传入的函数是什么? fetch应该执行它的原始回调函数,然后这个参数是作为回调的参数吗?我当然很困惑。

^我理解这是两个不同的问题 - 如果这会引起问题我将删除它,并将其发布在一个新的单独问题中,但我只是想,因为有人可能已经通过了整个代码,也许他已经'她/她已经装备好回答第二个问题了,我不妨问......

感谢提前!

3 个答案:

答案 0 :(得分:2)

如果你来自像Java这样的面向对象的世界,'这个'是一个不同的概念。在像Java这样的语言中,“this”指的是当前正在执行的对象,并由声明方法的方式定义。但是,在Javascript中,“this”指的是函数是如何被调用的,并且实际上是函数的执行上下文。事实上,引用John Resig的“Javascript Ninja的秘密”,它应该被称为调用上下文。

回答你的问题:

    this函数中的
  1. init指的是myChat对象。不,您使用jQuery.extend合并这两个对象的事实与此值无关。这在jQuery方面有点误导。

  2. this中的
  3. updateMessages也指myChat对象

  4. 在上面的代码中要注意的一件事是setInterval中的refresh部分。您的代码是正确的,因为它显式调用myChat对象上的函数,但在该函数中,this引用了全局对象(如果您正在运行,则很可能是“window”浏览器)。

    最后,为了回答关于回调的第三个问题,fetch运行异步POST。该POST完成后,将调用done回调。从done回调返回的值是调用传递给fetch的函数的值。在您的示例中,由于您的函数调用undefined,但display没有指定返回值,因此看起来是display。默认情况下,任何未指定返回的函数都将返回undefined

    希望有所帮助。

答案 1 :(得分:1)

在你的代码中,“this”几乎总是指myChat对象。

如果你打电话给init,你会写myChat.init()。 init是myChat对象的一部分,因此this引用包含对象。在myChat的范围内指定了Init,就像所有其他函数一样,这意味着此函数和所有其他函数都是myChat的一部分,因此thismyChat

var myChat = {

      init: function () {
        this.fetchInitialData();
        this.bindSendEvent();
        this.refresh();
      },
      ...
}

另外,如果查看extend(http://api.jquery.com/jQuery.extend/)上的jquery文档,则说明是“将两个或多个对象的内容合并到第一个对象中”。因此,当您$.extend(myChat, coreChat);时,您实际所做的是将所有属性从coreChat复制到myChat对象中。因此,当您在此代码中调用fetch时,实际上是在调用已复制到myChat对象中的fetch方法,因此this仍然引用myChat。为了进一步强化这些方法已添加到myChat对象中,请注意您正在调用myChat.display?这是在coreChat中定义的,但您可以使用myChat来访问它。

updateMessages: function () {
        this.fetch(function (messages) {
          myChat.display(messages);
        });
      }

有一个this未引用myChat的实例。这是coreChat的显示功能。由于您正在使用jquery .each函数,因此在该函数的范围内,this引用正在运行函数的列表项,而不是coreChat对象(或更确切地说是myChatcoreChat函数的var messageNode = $(".messages").find("li"); messageNode.each(function (i) { var $this = $(this); if ($this.text() !== messages[i]) { $this.text(messages[i]); } }); 副本,如上所述。)

fetch

至于问题的第2部分:

作为参数传递给fetch的函数是fetch完成时的回调函数。 fetch: function (fn) { 的定义包括一个函数作为参数:

.done

return fn(messages); 函数中,调用回调函数,传入消息数据,并返回该回调的结果:

.fetch

因此,您致电fetch并传入您的函数,fetch执行并执行所有处理,然后{{1}}调用您的传入函数。

答案 2 :(得分:0)

JavaScript中的

this取决于函数本身的使用方式。它会根据父对象,绑定/应用/调用调用,如果它与构造函数一起使用等而更改。请查看this on MDN以获取所有血腥细节。