web-dev-qa-db-ja.com

このJavaScriptのイディオムの基礎となるもの:var self = this?

WebKit HTML 5 SQL Storage Notes Demo のソースには次のようなものがあります:

function Note() {
  var self = this;

  var note = document.createElement('div');
  note.className = 'note';
  note.addEventListener('mousedown', function(e) { return self.onMouseDown(e) }, false);
  note.addEventListener('click', function() { return self.onNoteClick() }, false);
  this.note = note;
  // ...
}

著者はselfをいくつかの場所(関数本体)で使用し、this他の場所(メソッドの引数リストで定義された関数の本体)。どうしたの?一度気づいたので、どこでも見られるようになりますか?

346

こちらをご覧ください alistapart.comの記事

selfは、コンテキストが変更されている場合でも、元のthisへの参照を維持するために使用されています。これは、イベントハンドラー(特にクロージャー)でよく使用される手法です。

419

現代のブラウザは、通常のウィンドウまたはWebWorkerのグローバルオブジェクトを指す グローバル変数self を提供するため、変数名「self」はこの方法で使用しないでください。

混乱と潜在的な競合を避けるために、代わりにvar thiz = thisまたはvar that = thisを記述できます。

96
Duan Yao

はい、どこでも見ることができます。多くの場合、that = this;です。

イベントによって呼び出される関数内でselfがどのように使用されるかを確認しますか?これらには独自のコンテキストがあるため、selfを使用して、Note()に入ったthisを保持します。

Note()関数の実行が終了した後にのみ実行できる場合でも、selfが関数で引き続き使用できる理由は、内部関数がにより外部関数のコンテキストを取得するためですclosure.

34
Nosredna

var self = thisイディオムが嫌いな場合は、コールバックで元のthisへの参照を維持するための代替プロキシパターンがあることにも注意してください。

function.applyまたはfunction.callを使用して関数を特定のコンテキストで呼び出すことができるため、特定のコンテキストを使用してapplyまたはcallで関数を呼び出す関数を返すラッパーを作成できます。このパターンの実装については、jQueryのproxy関数を参照してください。以下に使用例を示します。

var wrappedFunc = $.proxy(this.myFunc, this);

その後、wrappedFuncを呼び出して、コンテキストとしてthisのバージョンを使用できます。

28
Max

JavaScriptの癖です。関数がより適切にメソッドと呼ばれるオブジェクトのプロパティである場合、thisはオブジェクトを参照します。イベントハンドラの例では、包含オブジェクトはイベントをトリガーした要素です。標準関数が呼び出されると、thisはグローバルオブジェクトを参照します。例のように関数をネストしている場合、thisは外部関数のコンテキストにまったく関係しません。内部関数は包含関数とスコープを共有するため、開発者はvar that = thisのバリエーションを使用して、内部関数で必要なthisを保持します。

9
kombat

変数は、メソッドで定義されたインライン関数によってキャプチャされます。関数内のthisは、別のオブジェクトを参照します。このようにして、外部スコープのthisへの参照を関数に保持させることができます。

9
Mehrdad Afshari

他の人が説明したように、var self = this;は、 closure のコードが親スコープを参照することを許可します。

ただし、現在は2018年であり、ES6はすべての主要なWebブラウザーで広くサポートされています。 var self = this;イディオムは、以前ほど重要ではありません。

arrow functions を使用することで、var self = this;を回避できるようになりました。

var self = thisを使用した場合:

function test() {
    var self = this;
    this.hello = "world";
    document.getElementById("test_btn").addEventListener("click", function() {
        console.log(self.hello); // logs "world"
    });
};

var self = thisなしで矢印関数を使用できるようになりました。

function test() {
    this.hello = "world";
    document.getElementById("test_btn").addEventListener("click", () => {
        console.log(this.hello); // logs "world"
    });
};

矢印関数には、独自のthisがなく、単に囲みスコープを想定します。

8
Elliot B.

実際、selfはウィンドウ(window.self)への参照です。したがって、var self = 'something'と言うと、selfがウィンドウオブジェクトに存在するため、それ自体へのウィンドウ参照をオーバーライドします。

これが、ほとんどの開発者がvar that = thisよりもvar self = this;を好む理由です。

とにかく; var that = this;はグッドプラクティスに沿っていません...あなたのコードが他の開発者によって後で修正/修正されることを前提として、開発者コミュニティに関して最も一般的なプログラミング標準を使用する必要があります

したがって、var oldThis/var oThis /などのようなものを使用する必要があります-スコープ内で明確にするために// ..はそれほどではありませんが、数秒と少数の脳サイクルを節約します

5
SorinN

上記で何度か言及したように、「自己」は、関数に入る前に「これ」への参照を維持するために単に使用されています。関数の中にある「this」は何か他のものを指します。

0
Cyprien