クラスで非同期関数を使用する場合、関数本体の関数を呼び出しているクラスオブジェクトにアクセスできない場合に問題がしばしば発生します。 これは、ajaxの例(jQueryを使用)で明確に見られます。
function Loader() { this.load = function() { $.ajax({ url: '/test.php', success: function(data, textStatus, jqXHR) {
この問題を解決するために、オブジェクトのコンテキストで任意の関数を呼び出すことができるjavascriptの
適用関数があり
ます 。 これが私たちの言うことです。 非同期関数を生成するコールバック関数を作成するためだけに残ります。
function cb(object, fnc) { return function() { return fnc.apply(object, arguments); } }
object-これに置換されるオブジェクト
fnc-実行可能関数
arguments-関数引数の標準オブジェクト
結果は次のようになります。
function Loader() { this.load = function() { $.ajax({ url: '/test.php', success: cb(this, this.onLoad) }) } this.onLoad = function(data, textStatus, jqXHR) { console.log(this);
オブジェクトの関数を関数として転送する必要はありません。その場で関数を作成できます。
cb(this, function(data, textStatus, jqXHR) { console.log(this); });
元のthisオブジェクトを保存する
前の例では、成功関数を呼び出したオブジェクト(内部jQueryオブジェクト)を失いましたが、呼び出しオブジェクトを使用する必要があることがよくあります。 たとえば、HTML要素イベントの場合:
function Button() { this.render = function() { var submit = $('<button>').html('click me'); submit.bind('click', function(event) {
この例では、ボタンのHTML要素のクリックイベントが発生します。 呼び出し関数のオブジェクト(この場合、ボタンのHTML要素)を保存するために、コールバック関数は次の形式を取ります。
function cb(object, fnc) { return function() { var args = [this]; for (var i in arguments) args.push(arguments[i]); return fnc.apply(object, args); } }
したがって、呼び出し元は関数の最初の引数として渡され、残りの引数は同じ順序で渡されます。 結果は次のようになります。
function Button() { this.render = function() { var submit = $('<button>').html('click me'); submit.bind('click', cb(this, this.onClick)); submit.appendTo($('body')); } this.onClick = function(target, event) { console.log(this);