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

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

ただいまの
回答率

89.99%

【jQuery】thisを使った「直接書いたコード」と「関数に切り出したコード」で処理が変わるのはなぜ?

解決済

回答 3

投稿

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

k499778

score 521

この投稿は前回の続きになります。
【jQuery】labelの中の文字列だけを変更したい
【jQuery】引数にthisを渡せない

今回以下のようなコードを書いて、「緑のボックスをクリックすると、ピンクのボックスの文字が変わり、またラベルの中のテキストノードだけを変更する」処理を実装していました。

イメージ説明

<!DOCTYPE html>
<html>

<head>
  <meta charset="UTF-8">
  <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
  <style>
    .aaa {
      width: 150px;
      height: 50px;
      background-color: #EFE;
      border: solid 1px #CCC;
      position: absolute;
    }

    .ddd {
      width: 150px;
      height: 50px;
      background-color: pink;
      border: solid 1px pink;
      position: absolute;
    }
  </style>
</head>

<body>
  <label class="aaa">
    <span class="bbb"></span>
    <input type="hidden" class="ccc">りんご
  </label>
  <br>
  <br>
  <br>
  <label class="aaa">
    <span class="bbb"></span>
    <input type="hidden" class="ccc">いちご
  </label>
  <br>
  <br>
  <br>
  <label class="aaa">
    <span class="bbb"></span>
    <input type="hidden" class="ccc">ぶどう
  </label>
  <br>
  <br>
  <br>
  <label class="ddd">
    <span class="bbb"></span>
    <input type="hidden" class="ccc">りんご
  </label>
  <script>
    $(function() {
      $(".aaa").on("click", function() {
        //labelの中の文字列だけを変更する処理。
        //直接書いたコード
        // var txt = $(this).text();
        // $(".ddd").contents().filter(function(){ return this.nodeType === this.TEXT_NODE }).remove();
        // $(".ddd").append(txt);
        test(this);
      });
    });

    //関数に切り出すとおかしくなる
    function test(_this){
      var txt = $(_this).text();
      $(".ddd").contents().filter(function(){ return _this.nodeType === _this.TEXT_NODE }).remove();  //文字がどんどん追加される。removeできていない。
      // $(".ddd").contents().filter(function(i,e){ return e.nodeType === e.TEXT_NODE }).remove();  //できる。
      // $(".ddd").contents().filter(function(e){ return e.nodeType === e.TEXT_NODE }).remove(); // 「i」をなくすと、spanタグやinputタグも消えてしまう
      // $(".ddd").contents().filter(function(e){ return e.nodeType === Node.TEXT_NODE }).remove(); // 「i」をなくし、Node.TEXT_NODEにすると、文字がどんどん追加される。removeできていない。

      $(".ddd").append(txt);
    }
  </script>
</body>

</html>

ただ「直接書いたコード」だと何ら問題ないのですが、「this」を引数に渡すといろいろと処理が変わっていしまいます。
そこでいくつか質問があります。

1つ目
そもそも関数の引数に「this」を渡したい時
直接書いたコードのまま関数に切り出せる場合と切り出せない場合の違いはどのようなときか?
「切り出せない場合」とは、「直接書いたコードを一部変更しなくてはいけない」場合のことです。
今回の場合は、thisをそのまま使うやり方はダメで、function(i,e)のようにしてeオブジェクトを使わなければいけない理由は何でしょうか?

2つ目
function(i,e)の「i」を消すと、spanタグやinputタグも消えてしまうのはなぜでしょうか?
「i」について調べて、i番目などを指すときに使うものだと思っています。
またこのコードで「i」を使っていないのに影響していることが不思議です。

3つ目
function(i,e)の「i」を消し、「=== e.TEXT_NODE })」のときと「=== Node.TEXT_NODE })」のときで処理の内容が変わるのはなぜでしょうか?

「=== e.TEXT_NODE })」のとき
・spanタグやinputタグも消えてしまう

「=== Node.TEXT_NODE })」のとき
・removeされず、文字がどんどんappendされてしまう

このどれかだけでもいいので質問に答えていただけると助かります。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 3

checkベストアンサー

+1

  • 1番目

filterのfunction内のthisはfilterでループされる要素を示します。
なので、関数内のfilterの中を_thisからthisに変えるとちゃんと動きます。

公式でも、

A function used as a test for each element in the set. this is the current DOM element.
functionはそのセットの中のエレメントの各々をテストするために使います。thisはそのカレントDOMエレメントを示します。

と書かれています。

  • 2番目

function(item,element)のitemを消したらfunction(element)にはなりません。
function(item)になります。引数の名前ではなく順序が大事です。

  • 3番目

これも2番目に共通です。
int.TEXT_NODEという定数は存在しないので、挙動が変わります。
Node.TEXT_NODEと、funciton(i,e)e.TEXT_NODEは同じ値を示します。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/03/25 16:02

    回答ありがとうございます!
    functionに関してもう一度勉強し直します。

    キャンセル

+1

以下の直接書いた場合の1行目のthisと2行目のthisは違うthisです。

// var txt = $(this).text();
// $(".ddd").contents().filter(function(){ return this.nodeType === this.TEXT_NODE }


なので関数に切り出す場合はこうするべきでは無いかと思います。

function test(_this){
  var txt = $(_this).text();
  $(".ddd").contents().filter(function(){ return this.nodeType === this.TEXT_NODE }).remove();

  $(".ddd").append(txt);
}

以下については、あなたはiを無くしたつもりかもしれませんが、実際になくなっているのはe、つまり2番目の引数の方です。eのつもりでiを使っているのですからそれはおかしくなるでしょう。

// $(".ddd").contents().filter(function(e){ return e.nodeType === e.TEXT_NODE }).remove(); 
// 「i」をなくすと、spanタグやinputタグも消えてしまう

// $(".ddd").contents().filter(function(e){ return e.nodeType === Node.TEXT_NODE }).remove(); 
// 「i」をなくし、Node.TEXT_NODEにすると、文字がどんどん追加される。removeできていない。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/03/25 16:03

    回答ありがとうございます!
    もう一度functionの使い方やthisについて調べてみます!

    キャンセル

+1

thisは、functionの呼び出し元を指します。
つまり、
clickのコールバックで呼ばれるfunction内のthis
filterのコールバックで呼ばれるfunction内のthisはそれぞれ別物を指します。
ですが、現在のソースでは _thisを使って全て同じ参照としているので挙動が違っています。(_this = clickのコールバックのthis)

filter内で参照するのをthisにすれば想定どおりの動きになると思います。

var _this = null;
$(".aaa").on("click", function() {
    this; // clickされた.aaaの参照

    _this = this;

    $(".ddd").contents().filter(function(){
        this; // .dddに含まれる各要素の参照

        _this; // こっちは、clickされた.aaaの参照
    }).remove();
});

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2016/03/25 16:02

    回答ありがとうございます!
    functionの使い方をもう一度勉強したみます。

    キャンセル

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

  • ただいまの回答率 89.99%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる