2016-05-05 5 views
0

私はこのキーワードをjavascriptで理解しようとしていますが、私はさまざまな記事を読んでいますが、まだ混乱しているようです。javascriptでこのキーワードにバインド

例えば以下のコードを考えてみましょう:

/* 
* script.js 
*/ 

var data = 'global data'; 

var myObj = { 

    data: 'object data', 

    scope: function() { 
     console.log(this.data); 
    } 

}; 


myObj.scope(); // print "object data" 

だからこの場合はスコープ()関数の呼び出しコンテキストはオブジェクトであり、このは、オブジェクト自体にバインドされています。

今、このが参照クリックイベントではスコープ()関数

document.getElementById("button").addEventListener('click', myObj.scope, false); 

// click on the button => print "undefined" 

をトリガするために

<!DOCTYPE html> 
<html lang="en"> 
<head> 
    <meta charset="UTF-8"> 
    <title></title> 
</head> 
<body> 

<input type="button" value="clickme" id="button"> 

<script src="script.js"></script> 

</body> 
</html> 

..さんは、いくつかのHTMLを追加してみましょう...とボタンのクリックイベントリスナーデータプロパティを持たないボタンオブジェクトに渡すので、undefinedが正しく出力されます。 今、私は宣言時に(コールまたは適用の代わりに)バインドメソッドを使用してこの問題を修正したいと考えています。したがって、私は書く:

/* 
* script.js 
*/ 

var data = 'global data'; 

var myObj = { 

    data: 'object data', 

    scope: function() { 
     console.log(this.data); 
    }.bind(this) 

}; 

document.getElementById("button").addEventListener('click', myObj.scope, false); 


myObj.scope(); // print "global data" 

// click on the button => print "global data" 

私が代わりにこのmyobjのグローバルオブジェクト(ウィンドウ)にバウンディングいているようです。どうして? こののキーワードは、console.log(this.data)最初の例では、bind(this)最後の例で使用されていますか?両方ともmyObjを参照するべきではありませんか? 私はこの点についていくつかの混乱があると確信していますので、事前に説明してくれてありがとうございます:)

+0

'myObj.scope.bind(myObj)'を 'addEventListener'に渡す必要があります。オブジェクトリテラルの内部で関数をバインドすることはできません。 – Bergi

+0

それはあなた自身が関数 'myObj.scope'を渡すだけなので、' myObj'からその関数を抜き取ってそれ自身の関数として張っていると、その関数がどのように見えるかを考えます。アクセスしようとしている範囲をどのように知っていますか?このようにデータを構造化する必要がありますか?代わりに、どのようなスコープのパラメータを取る関数を持つ必要があります –

+0

可能な複製[JavaScriptの "this"キーワードはオブジェクトリテラル内でどのように動作しますか?](http://stackoverflow.com/q/13441307/1048572 ) – Bergi

答えて

0

Why? Which is the difference between the this keyword used in the line console.log(this.data) in the first example and the one used in the line bind(this) in the last example? Should not both refer to the myObj? I am sure I have some confusion about this point, so thanks in advance for any explanation :)

var myObj = { 

    data: 'object data', 

    scope: function() { 
     console.log(this.data); 
    }bind(this) 

}; 
  1. まず、あなたがバインドする前に、ドットが欠落しているが、私はそれだけで
  2. bind(this)をタイプミスだと思う、ここでこれは」doesnのtはmyObjオブジェクトを指します。これはグローバルオブジェクトを指します。どうして?コードが実行されているコンテキストがグローバルコンテキスト(関数外のコード)であるため、myObj.scopeのコンテキストをmyObjにバインドしたい場合は、 「can't read property of undefinedエラーを持っているでしょう:

-

var myObj = { 

    data: 'object data', 

    scope: function() { 
     console.log(this.data); 
    }.bind(myObj) 

}; 

なぜ?上記のコードスニペットは1つのjavascript文であるため、javascriptエンジンが文を解釈しようとすると、myObjはまだ初期化されていません。初期化中ですので、関数bind(myObj)の場合、myObjは未定義です。

var myObj = { 

    data: 'object data', 

    scope: function() { 
     console.log(this.data); 
    } 
}; 
myObj.scope = myObj.scope.bind(myObj) 
+0

ありがとう!それが私が欠けていた点です。 – revy

+0

ちょっとしたメモとして。私は通常、コンストラクタメソッドを使ってオブジェクトを構築するのが好きなので、次のようにします。 function MyObject(){ this.scope = this.scope.bind(this); this.data = 'オブジェクトデータ'; } MyObject.prototype.scope = function(){ console.log(this.data); }; var myObj = new MyObject(); このようにして、構築されたインスタンスは、 'new'キーワードだけでオブジェクトを構築するたびにバインドする必要なく、バインドされた関数を持つことがわかります。 –

0

ここで解決策は、必要なコンテキストにeventHandlerをバインドする必要があります。

var data = 'global data'; 

var myObj = { 
    data: 'object data', 
    scope: function() { 
     console.log(this.data); 
    } 
}; 

document.getElementById("button").addEventListener('click', myObj.scope.bind(myObj), false); 

あなたが(ちょうどBabeljsについて読み、あなたは今日、それを使用することができます)脂肪の矢印を使用してES6上の例を参照してください、bindを気にしたくない場合は:明確にするために、次の例を見てください。

var data = 'global data'; 

var myObj = { 
    data: 'object data', 
    scope: function() { 
     console.log(this.data); 
    } 
}; 

document.getElementById("button").addEventListener('click',() => myObj.scope(), false); 

記事(https://john-dugan.com/this-in-javascript/)をお読みくださいより多くを学ぶために4つのステップで簡単

+0

この答えを詳しく説明します:関数がドット構文なしで呼び出されたとき( 'object.fnではなく' fn() ) ')の場合、' this'のスコープは 'null'に設定されます。つまり、グローバルスコープにデフォルト設定されます(ブラウザでは常に' window'です)。この答えを説明するように、関数を 'bind()'することでこの動作を無効にすることができます。どのように関数が呼び出されても、 'this'は最初の引数として' bind() 'に渡すものを参照します。 –

+0

答えをありがとう。私はこれを受け入れられたとマークしますが、私はなぜ3番目の例でbind(this)がmyObjではなくwindowオブジェクトを参照するのか理解できません。どんな手掛かり? – revy

+0

ええ@KlemenSlavičはとてもうまく説明しました! (詳細は4つの簡単なステップでこれを説明している記事(https://john-dugan.com/this-in-javascript/)をご覧ください) – punkbit

0

それはオブジェクト内で直接オブジェクト自体に機能をバインドすることはできないようです、これを説明する:例を参照してください。が、オブジェクトの宣言があまりにも動作するようです外のオブジェクトを増強し、あなたは決してあなたが関数を呼び出すするたびコンテキストを結合するのに心配する必要はありません:

var myObj = { 
    data: 'object data', 
}; 

myObj.scope = function() { 
    console.log(this.data); 
}.bind(myObj); 

あなたはどう思いますか?あなたの最後のコードスニペットで

+0

はい、[それは動作します](http://stackoverflow.com/a/10711164/1048572)。 – Bergi

+0

ありがとう、まさに私が探していたもの – revy

関連する問題