2017-12-11 10 views
0

このコードを修正する必要があります。クリックごとにJavaScriptカウンターが増えますか?

<!DOCTYPE html> 
<html lang="en"> 
<head> 
    <meta charset="utf-8"> 
    <title>Clicker</title> 
    <meta name="description" content=""> 
    <style></style> 
</head> 
<body> 
    <button>Click!</button> 

<script> 
    const counter = { 
     cnt: 0, 

     inc: function() { 
      cnt++; 
      console.log(cnt); 
     } 
    }; 

    const button = document.getElementsByTagName('button')[0]; 
    button.addEventListener('click', counter.inc, false); 

</script> 
</body> 
</html> 

その背後にある概念である私は今罰金が、わからない働きいる解決策、解決策は次のとおりです。

inc: function() { 
    counter.cnt++; 
    console.log(counter.cnt); 
} 
+0

'cnt ++'が 'counter '内で同じ' cnt'をインクリメントしていない場合、 'counter.cnt'を使ってインクリメントする必要があります。 – gurvinder372

+0

欠けている概念は、基本的にスコープに関係しています。コードのどの部分がどの変数を参照できるか。 – Sirko

+0

したがって、グローバル変数 'cnt'がないので、あなたのコードは' counter.cnt'で動作します。他の問題はありますか? – Justinas

答えて

7

そのわずかscoping問題、

//Right approach would be, 

const counter = { 
    cnt: 0, 
    inc: function() { 
    this.cnt++; 
    console.log(this.cnt); 
    } 
}; 

エラーが発生したコードは、現在のスコープで宣言された変数cntを探し、グローバルスコープまでトラバースします。参照が見つからない場合は、エラーがスローされます。

イベントリスナーとしてincを渡すので、そのスコープをバインドする必要があります。それ以外の場合は、その関数内のthisがイベントをトリガーする要素をポイントします。この場合、要素はbuttonになります。

button.addEventListener('click', counter.inc.bind(counter), false); 

または、最も読みやすいアプローチは次のようになり、

button.addEventListener('click', function() { 
counter.inc() 
}, false); 

.bindを回避するもう1つの理由は、あなたが.bindを使用して関数にコンテキストをバインド一度場合、です。その後、そのコンテキストを上書きすることはできません。使用する場合も.call/.apply

+1

これは本当に機能しますか? 'addEventListener()'だけが 'inc()'関数自体を指しているので、 'this'のコンテキストは失われます。 – Sirko

+1

@Sirkoええ、それは '.bind'を使ってOPによって処理されなければなりません。私も同様にお勧めします。 –

+0

@Sirkoそれは必要ですが、不十分です – Alnitak

1

this.cntを使用して、関数内の変数cntにアクセスします。

inc: function() { 
      this.cnt++; 
      console.log(this.cnt); 
     } 

また、あなたがこのような関数内counterthisの値をバインドする必要があります。

button.addEventListener('click', counter.inc.bind(counter), false); 

、について説明:

は、ここでは、2番目の引数としてcallback機能を提供しています〜addEventListenerに機能します。このコールバック内のthiscounterオブジェクトと等しくなるように、私たちはbindを使用しています。 MDNウェブドキュメントによれば

バインド()メソッドは、呼び出されたときに、任意の提供先行 引数の所定の配列を備えた値に設定し、その このキーワードを持つ新しい関数を作成新しい関数が呼び出されたとき。

したがって、コールバックの内側thisの値はcounterに設定されていると我々はthis.cntとしての性質cntにアクセスすることができます。登録したコールバックとして

() => counter.inc() 

(あなたがES6を使用しているように見えるので)

counter.inc.bind(counter) 

か:button.addEventListener()

+0

このキーワードは機能しません。なぜかわからない –

+0

あなたは同じ方法で使用していますか?どの出力が得られているのですか? –

+0

をクリックするとNaNが返されます –

1

あなたが のいずれかを使用する必要があります呼び出します。

incメソッド内の正しいcnt(つまりthis.cnt)も参照する必要があります。

1

あなたのコードに問題がある:あなたが望むよう

inc: function() { 
    cnt++; 
    console.log(cnt); 
} 

CNTは、グローバル変数ではなく、カウンタのプロパティを参照します。 this.cnt++を使用して設定する必要があります。

2番目のことは、addEventListenerをバインドするときに関数を渡すだけなので、関数が呼び出されるときにthisというコンテキストが実際にはカウンタではありません。

button.addEventListener('click', function() { 
     counter.inc(); 
}, false); 

or button.addEventListener('click',() => counter.inc(), false); 

かのように対抗するcounter.incをバインドします:あなたはそれを変更する必要があるという概念は、あなたがしているということです

counter.inc = counter.inc.bind(counter); 
1

するオブジェクトリテラルである、オブジェクトリテラルは、それを囲む、データをカプセル化これはグローバル変数の使用を最小限に抑えます。これは、コードを組み合わせるときに問題を引き起こす可能性があります。最初の例では、グローバルなcnt変数を取得し、グローバルスコープに存在しない変数をインクリメントしていますそのオブジェクトのプロパティとメソッドを取得するためには、最初にオブジェクトを呼び出す必要があります。次に、このオブジェクトのようなプロパティです(メソッドまたはプロパティ)

関連する問題