質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

Q&A

解決済

1回答

1154閲覧

関数内関数におけるthisの適用範囲について

Null0lluN

総合スコア59

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

0グッド

0クリップ

投稿2019/02/26 12:00

以下のコードで[].forEach.call内の関数が働かない理由と、どうしたら働くのかを教えていただけますと幸いです。

html

1<!doctype html> 2<html lang="jp"> 3<body> 4 <div class="container"> 5 a 6 </div> 7 <div class="container"> 8 b 9 </div> 10 <div class="container"> 11 c 12 </div> 13 <div class="container"> 14 d 15 </div> 16 <div class="container"> 17 e 18 </div> 19</body> 20<script type="text/javascript" src="test.js" charset="UTF-8"></script> 21</html>

js

1let TEST = function() 2{ 3 this.func_sub = function() 4 { 5 console.log("func_sub"); 6 } 7 8 this.func = function() 9 { 10 this.func_sub(); 11 let span = document.querySelectorAll('div'); 12 [].forEach.call 13 (span, function(s) 14 { 15 s.addEventListener('load', this.func_sub, false); 16 this.func_sub(); 17 } 18 ); 19 } 20} 21let test = new TEST(); 22test.func();

疑問点

  • forEach.call内のfunc_subがどちらも働かない理由
  • Uncaught TypeError: this.func_sub is not a functionというエラーがthis.func_sub();に対して出るのに、addEventListener内のthis.func_subには出ない理由
  • どうやったら、[].forEach.call内でfunc_subを働かせられるのか

以上です。よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

JS特有のイベント駆動の時のツラミですね。
イベント登録時に使い捨ての無名関数作って渡してやってますが、
この無名関数でスコープが切られてそれに紐づくthisが生成されるので動作しなくなります。

素直に修正するならばthisを別の変数として定義して保管しましょう。

JavaScript

1 this.func = function() 2 { 3 // thisをselfとして定義、慣習としていろんなライブラリでselfという変数名が使われる 4 let self = this; 5 6 this.func_sub(); 7 let span = document.querySelectorAll('div'); 8 [].forEach.call 9 (span, function(s) 10 { 11 // selfで再定義した為、thisの上書きも何のそので実行できる 12 s.addEventListener('load', self.func_sub, false); 13 self.func_sub(); 14 } 15 ); 16 }

letを変数定義に利用しているのはES2015だからIE11は切り捨てるという意思表示でしょうか?
そうであればthis周りは初心者には解決出来ないのでES2015で追加されたクラス構文を使ってください。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Classes

ES2015流儀の書き方でリファクタリングしつつ動作させるとこうなります。

JavaScript

1// クラス名は先頭文字大文字のキャメルケースにすること 2class Test { 3 // メソッド名はキャメルケースにすること 4 funcSub () { 5 console.log('func_sub'); 6 } 7 8 func () { 9 this.funcSub(); 10 // div掴んでるのに変数名spanってなんだよ…divに変更 11 const div = document.querySelectorAll('div'); 12 // 無名関数からアロー関数に変更することでthisの上書きを阻止 13 [].forEach.call(div, it => { 14 // thisはそのまま使える 15 it.addEventListener('load', this.func_sub, false); 16 this.func_sub(); 17 }); 18 } 19} 20const test = new Test(); 21test.func();

投稿2019/02/26 12:20

編集2019/02/27 07:22
miyabi-sun

総合スコア21158

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Null0lluN

2019/02/26 12:37

ありがとうございます。 letを使ったのは、varよりもletを使うほうが良いというサイトを見たためです。 変数名spanは最初作ったテストコードがdivじゃなくてspanだったので、書き換えるのを忘れていました。ごめんなさい。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問