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

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

ただいまの
回答率

90.48%

  • JavaScript

    16991questions

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

javascriptのthisが何を指しているか?

解決済

回答 4

投稿

  • 評価
  • クリップ 1
  • VIEW 936

pato

score 24

<html>
  <head>
    <title>test</title>
    <style type="text/css">
      div{
        width:500px;
        height:300px;
        border:1px solid blue;
    }
    </style>
  </head>
  <body>

    <script type="text/javascript">

    function MyDiv(name){
        this.div = document.createElement("div");
        this.name=name;
        this.div.textContent="このdiv要素は"+name+"です";
        document.body.appendChild(this.div);

        this.div.addEventListener('click',function(e){
              console.log(this.name);
        },false);
    }

    var div1 = new MyDiv("div_1");
    </script>
  </body>
</html>
javascriptで動的にdiv要素を作って、それをクリックしたらそのdiv要素のnameプロパティの値がコンソールに表示される、というスクリプトなんですが、実行すると結果は「undefined」になります。
「イベントを元に関数を呼び出した場合、関数内の this はイベントの発生元の要素を指す」と認識していました。この場合addEventListenerの第2引数の関数内のthisは、
イベント発生元であるインスタンスdiv1を指すのでコンソールには「div_1」と表示されるのではないかと思うのですが、なぜ結果がundefinedなのでしょうか?
  • 気になる質問をクリップする

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 4

+1

this.name=name;
ではなく、
this.div.name=name;
の間違いでしょうか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/07/19 13:22

    あるサイトのサンプルなんですが、そのサンプルでは
    this.name=name;
    となってます。質問に「div要素のnameプロパティ」と書いてしまいましたが、MyDivはコンストラクタなので、そのコンストラクタから生成されたインスタンスdiv1のnameプロパティの値、と書くべきでしたかね。

    キャンセル

+1

JavaScriptのthisは関数が実行される環境での自分自身です。
これは特別な変数で、クロージャの変数束縛から除外されています。
addEventListenerに引数として引き渡されたfunction(e) {...}は、
イベントが実行されたあとに実行される関数ですが、
その実行環境はfunction MyDiv(name){...}内では無いため
(rikさんが示したとおり、今回はdivオブジェクトが実行環境になります)、
ここでのthisfunction MyDiv(name){...}内のthisが異なるものになります。
このように、コールバック等で関数に関数を渡す場合は、
その渡された関数の実行環境はつねに意識する必要があります。
また、Array.prototype.map()のようにthisが何になるかを指定することが
できる場合もあります。

で、今回の場合どうするかというと、方法は主に三つです。

1. Function.prototype.bind()thisを束縛する。
    bind()を使うと関数の実行環境を束縛できます。
    
    this.div.addEventListener('click', function(e) {
        console.log(this.name);
    }.bind(this), false);

2. ファットアロー=>を使用する。(ECMAScript2015から)
    ファットアローで作成した関数はthisも変数束縛してくれます。
    策定されたばかりのECMAScrpit2015からの新機能であるため、ほとんどのブラウザで
    まだ対応していません。※ Firefoxはすでに対応しているようです。
    実際に使うにはbabel等でECMAScript5に変換する必要があります。
    
    this.div.addEventListener('click', (e) => {
        console.log(this.name);
    }, false);

3. 適当な変数を作ってに入れる。
    this以外の変数であれば変数束縛により、クロージャの関数内でも同じものを示すよう
    になります。
    ですので、適当な変数_thisとかに入れておいてから使います。
    babel等でファットアローを変換したときもこのようになります。
    
    var _this = this;
    this.div.addEventListener('click', function(e) {
        console.log(_this.name);
    }, false);

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

checkベストアンサー

0

(ちょっと思考まとめ不足で自信ないのですが)

関数をコンストラクタ呼び出しした場合のthisは生成されるオブジェクトになるから
MyDiv内のthisはこれから生成されるオブジェクトを参照してると思います。
参考

var div1 = new MyDiv("div_1");
そしてこのdiv1に入っているのはHTMLのdivではなく、MyDivのオブジェクトかも。
イベントリスナーは生成したdivにつくけど、そのdivにはthis.nameは無いので
undefinedになっているのではないでしょうか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

コードに追記して実行してみました。
<html>
  <head>
    <title>test</title>
    <style type="text/css">
      div{
        width:500px;
        height:300px;
        border:1px solid blue;
    }
    </style>
  </head>
  <body>

    <script type="text/javascript">

    function MyDiv(name){
        this.div = document.createElement("div");
        this.name = name;
        this.div.name = 'div_2';
        this.div.textContent = "このdiv要素は" + name + "です";
        document.body.appendChild(this.div);

        this.div.addEventListener('click',function(e){
            console.log(this.name);
            console.log(div1.name);
        },false);
    }

    var div1 = new MyDiv("div_1");
    </script>
  </body>
</html>
div_2
div_1
と表示されます。
つまり、this.div.addEventListener内のfunction(e){...}では
thisは div を示すもので、MyDiv を示すものではないという事だと思います。
私はthisは混乱のもとですので極力使わない様にしていますし使わなくても何とかなります。
使った方がいいという方もおられるでしょう。
「javascript this」で検索すると詳しく解説しているサイトが見つかります。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2015/07/20 12:32

    解答ありがとうございました。MyDivクラスのインスタンス(オブジェクト)と、createElementメソッドで返されて変数divに代入されるオブジェクトは別のものなんですよね。その違いがわかっていませんでした。頂いたコードだとその違いがよくわかります。

    キャンセル

関連した質問

同じタグがついた質問を見る

  • JavaScript

    16991questions

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