【问题标题】:jquery oop override method functionjquery oop覆盖方法函数
【发布时间】:2013-06-07 10:14:03
【问题描述】:

您好,如果我的方法是这样声明的,我想知道如何覆盖方法函数:

(function ($) {
    $.extend({
        tablesorter: new
        function () {
            function buildHeaders(table) {
                console.log('ORIGINAL HEADERS');
            }

            this.construct = function (settings) {
                return this.each(function () {
                    $headers = buildHeaders(this);
                });
            }
        }
    });

    $.fn.extend({
        tablesorter: $.tablesorter.construct
    });
})(jQuery);

我的目标是彻底重写tablesorter buildHeaders函数。

(function ($) {
    var originalMethod = $.fn.tablesorter;
    $.fn.tablesorter = function() {
        console.log('overiding');

        function buildHeaders(table) {
            console.log('OVERRIDE HEADERS');
        }
        originalMethod.apply(this, arguments);
    }
})(jQuery);

这不起作用...任何帮助都会很棒。谢谢!

【问题讨论】:

    标签: javascript jquery oop overriding


    【解决方案1】:

    $.extend 不是扩展 jQuery 的正确方法,而是一个 jQuery 实用方法。你应该使用$.fn.extend。然后它应该工作。如果没有尝试也使用

    (function ($) {
      var originalMethod = $.fn.tablesorter;
      $.fn.extend({
        tablesorter: function() {
          console.log('overiding');
    
          function buildHeaders(table) {
            console.log('OVERRIDE HEADERS');
          }
          originalMethod.apply(this, arguments);
        }
      })
    })(jQuery);
    

    您可以在这里阅读更多内容:http://api.jquery.com/jQuery.fn.extend/

    希望这会有所帮助。

    【讨论】:

      【解决方案2】:

      简短回答:不,你不能。

      函数内部的函数(即buildHeaders 是另一个函数内部的函数)是私有的,不能被覆盖。举个简单的例子,猜猜输出:

      // A very simple function inside a function
      test = function() {
        function buildHeaders() {
          alert("original buildHeaders called");
        }
      
        buildHeaders();
      }
      
      // Now lets take a backup of the "test" function
      oldTest = test;
      
      // And try to override a private function
      test = function() {
        function buildHeaders() {
          alert("duplicate buildHeaders called");
        }
      
        oldTest.apply(this, arguments);
      }
      
      // Call
      test();
      

      Guess the output?

      为什么?

      我认为您正在从 Java(或类似)背景中尝试此操作,您可以在其中覆盖实际方法。在 Javascript 中,您不会覆盖函数,而是替换它们。即

      function x() { }    // Original function
      oldX = x            // Original function is now oldX
      x = function() { }  // x is now a **NEW** function
                          // we did not override, we replaced
      
      // At this point, oldX and x are two different functions
      // You just swapped their names, but x is no longer the original x
      

      这部分很清楚。现在进入第二部分,私有/局部变量

      function x() {
        var y = 0;
      }
      x();
      alert(y); // No, you cannot access "y" from outside
      

      但是让我们采取:

      function x() {
        y = 0;  // Without "var"
      }
      x();
      alert(y); // Alerts "0"!!
      

      如果您提供var y = 0,它在该函数中将变为私有。如果你不这样做,它就会变成全局作用域(技术上来说是上限作用域,但我们暂时不考虑它)。

      第三部分,函数内部的函数默认是私有的。以同样的例子,

      function x() {
        function y() { }
        // this is the same as saying:
        var y = function() { }
        // note "var y", so you can't override this from outside
      }
      

      所以如果你通常在函数内部定义一个函数,比如function x() { function y() { } },那么yx 私有的。再加上你永远不能覆盖javascript中的函数,你只能替换。因此,您将永远无法访问或修改该 y,除非在原始 x 函数中。

      唯一的选择

      如果您有权访问某个函数,可以将其替换为自定义实现。因此,您必须编辑原始函数,或者以某种方式保存对 buildHeaders outside 函数的引用。即您必须执行以下操作之一:

      // ...
      tablesorter: new function() {
        this.buildHeaders = function() { }
        // ...
      }
      
      // and later, you can replace this:
      tablesorter.buildHeaders = function() { // alternative code }
      

      您将能够覆盖该函数,因为它不是私有的,并且您有一个句柄来访问它。

      编辑:小语法

      【讨论】:

      • 这对他的代码不起作用,因为$headers = buildHeaders(this); 找不到buildHeaders 函数了。请记住,this 指的是 jquery 对象,而不是 tablesorter
      • 如果 OP 将 buildHeaders 更改为对象函数,而不是当前的 function inside function,那么是的 - 他们必须更新代码的其他部分。因此,总体答案是不,您不能,当前代码并非旨在支持覆盖,任何更改都需要对现有代码进行轻微更改,这违背了 OP 的覆盖目标无需修补现有代码的事情。因此答案不,你不能
      【解决方案3】:

      有一些方法可以做到:

      • 像 RDX 的回答那样做:存储对 buildHeaders 的引用并完全替换它(请记住在 construct 函数中将上下文存储为 this 是指 jquery 对象,而不是 tablesorter)。
      • 为什么不采用更简单的方法:只需在您的第一个代码块中修改您的原始函数。我猜你不这样做的原因是因为你不想失去原始功能,否则你可以采用这种简单的方法而不是第一种方法。

      如果是这样的话,我在这里提出另一种基于template method design pattern 的方法。这种方法允许您完全覆盖模板方法的一部分而不会丢失原始函数。

      (function ($) {
          $.extend({
              tablesorter: new
              function () {
                  var self = this; //preserve the context
                  this.buildHeaders = function (table) {
                     //you can customize the template method anyway you want
                     this.buildHeadersCore(table);
                  }
      
                  this.buildHeadersCore = function (table){
                      console.log('ORIGINAL HEADERS');
                  }
      
                  this.construct = function (settings) {
                      return this.each(function () {
                          $headers = self.buildHeaders(this);//call via "self" instead of "this" because "this" now refers to jquery object, not the tablesorter anymore
                      });
                  }
              }
          });
      
          $.fn.extend({
              tablesorter: $.tablesorter.construct
          });
      })(jQuery);
      
      function inherit(proto) {
          var F = function() { };
          F.prototype = proto;
          return new F();
      }
      
      (function ($) {
          var tablesorterExtended = inherit($.tablesorter);
          tablesorterExtended.buildHeadersCore = function (table){
               console.log('OVERRIDE HEADERS');
          }
          $.fn.tablesorterExtended = tablesorterExtended.construct;
         //or you can even use your old name. The point is the original buildHeaders function is not lost when you replace.
         //$.fn.tablesorter = tablesorterExtended.construct;
      })(jQuery);
      

      【讨论】:

        猜你喜欢
        • 2021-12-07
        • 1970-01-01
        • 2011-05-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多