1

私はたくさんの投稿をしてきましたが、これのおかげで最終的に必要なものを手に入れました:

$("a.foo").click(function(){
    var that = this;
    jPrompt("Type something:","","", function(r) {
        $(that).text(r);
    }
}

以下より: コールバック関数内で $(this) にアクセスする

誰かがここで何が起こっているのか (this再割り当てしないと利用できないのはなぜですか?) と、どのコア情報を読むべきかについて詳しく説明できるかどうか疑問に思っていました。私が集めたものから、これは閉鎖と関係があるかもしれません...それは私が周りを検索しているときにぶつかったもののほとんどです. それは正確ですか?

私の場合、いくつかのコードを実行し、ajax リクエストが完了したらリダイレクトしようとしていました。私が実行していたコールバック関数では、$(this).attr("href")未定義を返していました。

4

4 に答える 4

3

this関数の呼び出し方法に応じて、javascript によって割り当てられます。したがって、コールバックを呼び出すときにコールバックに含まれるjPrompt()値を決定するのは関数です。 thisjPrompt()

そのため、jPrompt が、this渡された何らかの引数を介して同じ値を保持するために邪魔にならない限り、異なる値を持つ可能性があります。そのため、これまで行ってきたように、コールバック内でアクセスできるように保存できます。これは、javacscript コールバックの非常に一般的な設計パターンです。

this参考までに、割り当てられている方法のいくつか:

  • obj.method()-thismethod()設定されますobj
  • func.call(obj)-thisfunc()設定されますobj
  • func()- inまたはin strict モードthisに設定されますwindowfunc()undefined
于 2012-12-02T03:11:40.583 に答える
1

いくつかのコメントが追加された質問のコード:

$("a.foo").click(function(){
    var that = this; //`this` holds the a object clicked.  now so does `that`! 
    jPrompt("Type something:","","", function(r) { 
        //even if `this` has a different value here, `that` still holds the a object clicked
        $(that).text(r);
    }
}

これは、似たような状況で自分がやっていることがよくあることです。 thisコンテキストに依存し、thisあるコンテキストで持っていた値を保持し、別のコンテキストで使用する必要があることがよくあります。

ECMAScript 仕様からの引用:

10.1.7 これ

すべてのアクティブな実行コンテキストに関連付けられたthis値があります。thisの 値は、呼び出し元と実行されるコードのタイプによって異なり、制御が実行コンテキストに入ったときに決定されます。

それがあなたの質問に答えることを願っています。また、さらに読むためのリソースも求めました。来てください:

https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Operators/this

これらの人たちは、詳細で通常は非常に正確な優れたドキュメントを提供します (Google 検索で最初に表示されることが多い他の一般的な参考文献とは異なります -- w3csools.com 私はあなたのことを考えています!)。

于 2012-12-02T03:14:38.123 に答える
1

場所によって意味がthis変わります。クリック イベントのハンドラー内とは、関数に渡されるコールバック内this以外のものを意味します。thisjPrompt

ハンドラーに渡されるオブジェクトには への参照があるためthis、を再割り当てする必要はありません。eventcurrentTarget

$("a.foo").on("click", function (event) {
    // 'this' here refers to the anchor we clicked
    jPrompt("Type something:", "", "", function (r) {
        // 'this' here refers to whatever jPrompt instructs
        $(event.currentTarget).text(r);
    }
}
于 2012-12-02T03:17:18.223 に答える
1

の簡単な概要this

thisJavaScript では動的にスコープされます。その動作は、レキシカル スコープの他のすべての変数とは異なります。他の変数は、関数の呼び出し方法に応じて異なるバインディングを持ちません。それらのスコープは、スクリプトに表示される場所から来ます。ただし、動作が異なり、スクリプト内のどこに表示されるかではなく、呼び出される方法thisに応じて異なるバインディングを持つことができます。そのため、この言語を学習している人にとっては混乱の元になる可能性がありますが、熟練した JavaScript 開発者になるには、それを習得する必要があります。

は動的にバインドされるためthis、関数の呼び出し方法に基づいて値を変更する方法がいくつかあります。


JavaScript で関数を実行する場合、デフォルトthiswindowです。

function foo() {
    console.log(this);
}

foo(); // => window

this値はさまざまな方法で変更できます。1 つの方法は、関数をオブジェクトのメソッドとして呼び出すことです。

var x = {
    foo: function() {
        console.log(this);
    }
};
x.foo(); // => This time it's the x object.

もう 1 つの方法は、関数を使用するcallapply、特定のオブジェクトのコンテキストで実行するように指示することです。

function foo() {
    console.log(this);
}
foo.call(x); // => x object again
foo.apply(x); // => x object as well

callまたはapplyの場合nullundefinedデフォルトの動作が再び発生します。関数は のコンテキストで実行されますwindow

function foo() {
    console.log(this);
}
foo.call(null); // => window
foo.apply(undefined); // => window

ただし、ECMAScript 5 strict modeでは、thisデフォルトで window にならないことに注意してください:

(function() {

    'use strict';

    function foo() {
        console.log(this);
    }

    foo(); // => undefined
    foo.call(null); // => null
    foo.apply(undefined); // => undefined

})();

thisを使用bindして、関数が呼び出される前にオブジェクトにバインドすることもできます。

function foo() {
    console.log(this);
}

var bar = {
    baz: 'some property'
};

var foobar = foo.bind(bar);

foobar(); // => calls foo with bar as this

父になる: レイジー バインド / アンカリーイングthis

さらに進んで、 a に作用し、関数の最初の引数として値を渡すことがthisできる関数を使用したい場合があります。thisこれは、 などの配列メソッドに非常に役立ちますforEach。たとえば、配列に似ているが実際には配列ではないオブジェクトを扱っているとします。

var arrayLike = {
    '0': 'a',
    '1': 'b',
    '2': 'c',
    'length': 3
};

このオブジェクトを で反復処理する場合はforEach、次を使用できますcall

Array.prototype.forEach.call(arrayLike, function(item) {
    console.log(item);
});
// Logs: a, b, c

ただし、別のオプションはforEach、オブジェクトで直接呼び出すことができる関数を作成することです。

var forEach = Function.prototype.call.bind(Array.prototype.forEach);

これで、配列のようなオブジェクトを反復処理したいときはいつでもこの関数を使用できます。

forEach(arrayLike, function(item) {
    console.log(item);
});
// Logs: a, b, c

この方法は「非カリー化this」と呼ばれることもあります。ただし、これらの「カリー化されていない」関数を生成できる関数を作成し、それを「遅延バインディング」と呼ぶことを好みます。

var lazyBind = Function.prototype.bind.bind(Function.prototype.call);

var forEach = lazyBind(Array.prototype.forEach);
var slice = lazyBind(Array.prototype.slice);
var map = lazyBind(Array.prototype.map);

forEach(arrayLike, function(u) {
    console.log(u);
});
// Logs: a, b, c

var realArray = slice(arrayLike);
// Converts arrayLike into a real array

forEach(
    map(arrayLike, function(u) {
        return u + 'Q';
    }),
    function(u) {
        console.log(u);
    }
);
// Logs: aQ, bQ, cQ

この手法の素晴らしい点の 1 つは、セキュリティ保護可能な JavaScript を作成するのに役立つことです。これは、ページ上の他のスクリプトが内部変数を詮索したくない場合に役立ちます。ただし、これはかなり高度なメタプログラミング手法であり、日常の JavaScript では見られません。

于 2012-12-02T06:00:56.140 に答える