2017-09-26 10 views
0
(function() { 
    var tasks = /* Some awesome content stored here */ 
    var render = ''; 
    for(var x = 0; x < questions.length; x+= 1) { 
    render += '<p onclick="changeText(' + x +')">question[i]</p>' 
} 
    function changeText(x) { 
     // some fancy stuff happens here with a certain x 
    } 
})(); 

IIFEを使用しようとしたときに以下のエラーが発生するのはなぜですか?IIFEを取り除くとうまく動作します。私のものではないchangeText()は他のものと同じスコープですか?すぐに呼び出された関数式が私のonclickを妨害するのはなぜですか?

これを修正するにはどうすればよいですか?

Uncaught ReferenceError: changeText is not defined 
    at HTMLElement.onclick 
+0

親属性から呼び出すほうがよいでしょう。あなたのHTMLに 'p'がどこにあるのかを教えてください。 –

答えて

0

関数宣言は、現在のスコープで(その関数である値を持つ)変数を作成します。

onclick属性は、独自のスコープとグローバルスコープにのみアクセスできます。

IIFE内部の機能は範囲外です。


迅速かつ汚れた解決策は、changeTextをグローバルにすることです。


クリーンソリューション、大藤:

これはonclickの属性を使用しないでくださいもう一つの理由です。

文字列を混ぜ合わせてHTMLを生成しないでください。 DOMを直接生成し、addEventListenerを使用してください。

for(var x = 0; x < questions.length; x+= 1) { 
    var p = document.createElement("p"); 
    p.appendChild(document.createTextNode("question[i]"); 
    p.setAttribute("data-x", x); 
    p.addEventListener("click", function() { changeText(this.dataset.x); }); 
    something.appendChild(p); 
} 

NB:段落は、インタラクティブコントロールできるように設計されていません。クリックイベントを追加すると、ポインティングデバイスを使用していない(または使用できない)ユーザーにはアクセスできなくなります。代わりに、クリックするように設計されたもの(<button>など)を使用する必要があります。

+0

_「きれいな解決策」_:私は同意しません。ループ内でクリックハンドラを作成しないでください。 – Cerbrus

+0

@Cerbrusループでそのクリックハンドラをリベートするのはなぜ間違っているのか説明してください。これは美学の問題なのでしょうか、とにかくこのようなことをすることであなたのコードに影響しますか? – user19380947

+0

@ user19380947:質問が50件ある場合は、その機能の複製を50個作成しています。ループの外側で_once_という関数を作成し、それを 'addEventListener'に渡してください。 – Cerbrus

関連する問題