【问题标题】:How this and $(this) end up being the same when extending jQuery?扩展 jQuery 时 this 和 $(this) 最终是如何相同的?
【发布时间】:2013-04-24 16:03:13
【问题描述】:

我正在尝试使用一个像这样扩展 jQuery 的插件:

  $.extend({
    StatelessDeferred: function () {
        var doneList = $.Callbacks("memory"),
            promise = {
            done: doneList.add,

                // Get a promise for this deferred
                // If obj is provided, the promise aspect is added to the object
                promise: function (obj) {
                  var i,
                    keys = ['done', 'promise'];
                  if (obj === undefined) {
                    obj = promise;
                  } else {
                    for (i = 0; i < keys.length; i += 1) {
                      obj[keys[i]] = promise[keys[i]];
                    }
                  }
                  return obj;
              }
            },
            deferred = promise.promise({});

          deferred.resolveWith = doneList.fireWith;

      return deferred;
      }
    });

问题是(我什至不确定是不是这里引起的),在回调加载后,在 done 回调中,this$(this) 是相同的,所以我最终得到例如: this === $(this) === $(document).

我不确定我是否理解正在扩展的内容。除了错误分配外,该插件可以正常工作。

问题:
上述扩展是否会导致this === $(this) === $(document)

编辑: 完整插件(120 行):

"use strict";

(function (window, $) {
  $.extend({
      StatelessDeferred: function () {
        var doneList = $.Callbacks("memory"),
          promise = {
            done: doneList.add,

            // Get a promise for this deferred
            // If obj is provided, the promise aspect is added to the object
            promise: function (obj) {
              var i,
                keys = ['done', 'promise'];
              if (obj === undefined) {
                obj = promise;
              } else {
                for (i = 0; i < keys.length; i += 1) {
                  obj[keys[i]] = promise[keys[i]];
                }
              }
              return obj;
            }
          },
          deferred = promise.promise({});

        deferred.resolveWith = doneList.fireWith;

        // All done!
        return deferred;
      }
    });

  var routes = [],
    current_priority = 0,
    methods = {
      add: function (pattern, priority) {
        var i = 0,
          inserted = false,
          length = routes.length,
          dfr = $.StatelessDeferred(),
          context = $(this),
          escapepattern,
          matchingpattern;
        if (priority === undefined) {
          priority = 0;
        }
        if (pattern !== undefined) {
          // http://simonwillison.net/2006/Jan/20/escape/
          escapepattern = pattern.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
          matchingpattern = escapepattern
                          .replace(/<int:\w+>/g, "(\\d+)")
                          .replace(/<path:\w+>/g, "(.+)")
                          .replace(/<\w+>/g, "([^/]+)");
          while (!inserted) {
            if ((i === length) || (priority >= routes[i][2])) {
              routes.splice(i, 0, [new RegExp('^' + matchingpattern + '$'), dfr, priority, context]);
              inserted = true;
            } else {
              i += 1;
            }
          }
        }
        return dfr.promise();
      },
      go: function (path, min_priority) {
        var dfr = $.Deferred(),
          context = $(this),
          result;

        if (min_priority === undefined) {
          min_priority = 0;
        }
        setTimeout(function () {
          var i = 0,
            found = false,
            slice_index = -1,
            slice_priority = -1;
          for (i = 0; i < routes.length; i += 1) {
            if (slice_priority !== routes[i][2]) {
              slice_priority = routes[i][2];
              slice_index = i;
            }
            if (routes[i][2] < min_priority) {
              break;
            } else if (routes[i][0].test(path)) {
              result = routes[i][0].exec(path);
              dfr = routes[i][1];
              context = routes[i][3];
              current_priority = routes[i][2];
              found = true;
              break;
            }
          }
          if (i === routes.length) {
            slice_index = i;
          }
          if (slice_index > -1) {
            routes = routes.slice(slice_index);
          }
          if (found) {
            dfr.resolveWith(
              context,
              result.slice(1)
            );
          } else {
            dfr.rejectWith(context);
          }
        });
        return dfr.promise();
      },
    };


  $.routereset = function () {
    routes = [];
    current_priority = 0;
  };

  $.routepriority = function () {
    return current_priority;
  };

  $.fn.route = function (method) {
    var result;
    if (methods.hasOwnProperty(method)) {
      result = methods[method].apply(
        this,
        Array.prototype.slice.call(arguments, 1)
      );
    } else {
      $.error('Method ' + method +
          ' does not exist on jQuery.route');
    }
    return result;
  };

}(window, jQuery));

所以我可以将它用作路由器并像这样设置路由:

 $(".element").add("route", "/foo/bar/<path:params>", 2).done(function(params){
     // do something, for example
     console.log(this);
     console.log($(this));
     console.log("which will be the same = $('.element'));
 });

希望现在更清楚了。

感谢观看。

【问题讨论】:

  • $(this) 不可能是 ===$(document),因为这些对象是函数调用的结果。
  • 让我添加一些代码。 1 分钟。
  • 当然。您是否正在使用缓存集合的插件?
  • 嗯。我想是的......(仍在尝试了解它是如何工作的)
  • 来自您的代码 $(this) !== $(document),尽管在您记录它们时它们看起来相同。

标签: javascript jquery extend jquery-deferred promise


【解决方案1】:

来自文档:

如果只有一个参数提供给 $.extend(),这意味着目标参数被省略。在这种情况下,jQuery 对象本身被假定为目标。

大多数情况下,jQuery 附加到您的文档中:$(document).ready()

我认为发生的事情是 jQuery 对象被包装到文档中。然后你将它与$.extend(myObject) 合并。这将返回一个既是 jQuery 对象又是 myObject 的对象。

【讨论】:

  • 您能否就这与问题的相关性提供一些解释?谢谢。
  • 嗯。我会查的。感谢您的想法
猜你喜欢
  • 2012-04-04
  • 1970-01-01
  • 1970-01-01
  • 2011-04-07
  • 1970-01-01
  • 1970-01-01
  • 2012-08-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多