9

こんにちは、メソッドが次のように宣言されている場合、メソッド関数をオーバーライドする方法を知りたいです。

(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);

これは機能しません...どんな助けも素晴らしいでしょう。ありがとう!

4

3 に答える 3

21

短い答え: いいえ、できません。

関数内の関数 (つまり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();

出力を推測しますか?

なんで?

実際のメソッドをオーバーライドする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

この部分は明らかです。次に、2 番目の部分であるプライベート/ローカル変数に進みます。

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() { } }yは に対してプライベートになりxます。これを、javascript で関数をオーバーライドすることはできず、置き換えることしかできません。したがって、元の関数y内からを除いて、その にアクセスしたり変更したりすることはできません。x

唯一の代替手段

関数にアクセスできる場合にのみ、関数をカスタム実装に置き換えることができます。したがって、元の関数を編集するか、何らかの方法で関数のbuildHeaders 外部への参照を保存する必要があります。つまり、次のいずれかを実行する必要があります。

// ...
tablesorter: new function() {
  this.buildHeaders = function() { }
  // ...
}

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

プライベートではないため、関数をオーバーライドでき、アクセスするためのハンドルがあります。

編集:マイナー文法

于 2013-06-17T14:21:12.827 に答える