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

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

ただいまの
回答率

90.76%

  • JavaScript

    15310questions

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

難しいjsコードを教えてもらったのですがお手上げ状態です。

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 320

takane

score 22

こんにちは。
午前中に下記で質問させていただいた者です。
https://teratail.com/questions/95118#reply-147746

質問中、解決方法としてとあるコードを頂きました。

getElementsByTagNameで導き出した配列のひとつひとつを取り出すといった内容のものだと思うのですが、読解がまったくできません。

ここ3時間ほど悩んでもう人に聞いてしまおうという段階になってしまいました。
yambejpさん、せっかく頂いたのにすみません。

いただいたコードはこちらです。

<script>
HTMLCollection.prototype.getElementsByTagName=function(i){
  var ret=[];
  Array.prototype.map.call(this,function(j){
    Array.prototype.push.apply(ret, Array.prototype.map.call(j.getElementsByTagName(i),function(k){
      return k;
    }));
  });
  return ret;
};
window.onload=function(){
var touchList = document.getElementById('aplication').getElementsByTagName('li').getElementsByTagName('img');
console.dir(touchList);
}
</script>
<ul id="aplication">
<li>test1</li>
<li><img src="test2.jpg" alt="test2"></li>
<li><img src="test3.jpg" alt="test3"></li>
<li><img src="test4.jpg" alt="test4"><img src="test5.jpg" alt="test5"></li>
<li>test6</li>
</ul>
<img src="test7.jpg" alt="test7">

自分なりに理解した内容をまとめます。

HTMLCollection.prototype.getElementsByTagName=function(i){ 

//HTMLコレクションにgetElementTagNameがついた場合はfunction①の内容を適用してください。function①は下記です

var ret=[]; //配列retをからのまま設定してください。

Array.prototype.map.call(this,function(j){ 

//配列のprototype情報のうちソースマップにcallメソッド①を適用してください。対象はthis(getElementsByTagName由来の配列)、内容はfunction②です。

//function②

Array.prototype.push.apply(ret, Array.prototype.map.call(j.getElementsByTagName(i),function(k){

//配列のprototype情報にapplyメソッドを足してください。(意味不明)。対象はret配列です。足す内容は、とある配列で、prototype情報のソースマップのうち、タグiにfunction③をかけたものです。functino③は下記です。

return k; //あらかじめ引数kをタグiと対応させておきました。kをかえす、つまりタグiを文字情報としてかえしてください。
}));
});
return ret; //これらすべてを踏まえたうえで、retに入れた情報をすべて表示してください。
};

特に下記がわかりません。

①new Arrayの意味はわかるのですが、Array単体で登場した時にその意味がわかりませんでした。
②push、call、applyの意味がwebで調べてもいまいちよくわかりません・・・

もしかしたらわからないところが増えて聞き直したり質問を増やすかも知れませんが
ヒントとなることはどしどしお教えくださると幸いです。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • mts10806

    2017/10/05 15:50

    本来は回答にそのままコメントで確認していく内容と思います。。

    キャンセル

  • yambejp

    2017/10/05 15:51

    動かないというのではなく、解説すればいいということですか?

    キャンセル

  • takane

    2017/10/05 16:04

    >mts10806さん あ、そうなのですか・・・。すみません、次からそうします (. .;)>yambejpさん はい、そうです。といっても私自身がまったくわかっていないので、聞き返してしまうかもしれませんが・・・

    キャンセル

回答 2

+5

JavaScriptの場合、オブジェクトとメソッドの関係は、かなりゆるいもので、プロトタイプを書き換えたり、他のオブジェクトに使うメソッドを借りてきたり、ということもできます。

まず、最初にあるHTMLCollection.prototype.getElementsByTagName = function(){...}ですが、これは「HTMLCollectiongetElementsByNameメソッドを追加する」ということになります。

逆に、callapplyを使えば、メソッドを利かせるオブジェクトを変えることができます。つまり、「Array.prototype.map.call(this, function(){...})」は、「配列にあるmapメソッドを、thisで動かす」という意味です(Array.prototype以下のメソッドは、大半がほかのオブジェクトにも使用可能です)。

Array.prototypeにあるメソッドのリストは、MDNのページの左カラムにずらずら並んでいます(ここではmappushが使われています)。

なお、「既存のオブジェクト(特に、JavaScriptやDOM標準である型)のprototypeにメソッドを追加する」というのはプロトタイプ汚染と呼ばれることもあるように、あまり評判の良くない方法です。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/10/05 16:25

    本当ですね。mapやpushはたくさんあるメソッドの一部という扱いなんですね。
    MDNのページをもっとよく調べてみます。
    ありがとうございます。

    キャンセル

checkベストアンサー

+3

 解説

一応解説を希望とのことですのでざっくり

まず、通常のdocument.getElementById('aplication').getElementsByTagName('li')で
得られるオブジェクトはHTMLCollectionだということはご理解ください。
console.log(document.getElementById('aplication').getElementsByTagName('li'));
とすれば、オブジェクトの種類がわかるとおもいます。
その上で、HTMLCollection全般に新しい機能つける処理がprototypeを変更することです

HTMLCollection.prototype.getElementsByTagName=function(i){
はHTMLCollection全般に新たに「getElementsByTagName」というメソッドをつけます
その際、実行されるのがfunction以降のいわゆるコールバック関数です
またfunctionに渡される引数iはgetElementsByTagName(xxx)と指定する際の引数xxxです。

戻り値は配列を想定していますので最初に
変数retを空の配列で初期化しておきます
var ret=[]; → var ret=new Array(); のような指定でもよいでしょう

HTMLCollection自体は複数のHTMLElementの集合ですから、中身を走査しないといけません。
ブラウザにもよりますがHTMLCollectionにはforEachやmapの機能がない場合が多いので
Arrayの機能を借ります、その方法が「Array.prototype.map.call」
Arrayが全般的に持っているmapというメソッドを呼び出して(callして)います。
mapの第一引数に指定したthisはHTMLCollection自身で
コールバックが参照するjは一つ抜き出したHTMLElementです

HTMLElementであるjから.getElementsByTagName(i)でHTMLCollectionを得ています
それを前述同様mapをつかって今度は1つずつHTMLElementであるkを受け取って
配列のpush機能をつかってretにどんどん投げ込んでいます
そうして全ての走査が終わるとretに全てのHTMLElementが保持された状態になるわけです。
最終的に出来上がったretをreturnすることでHTMLCollectionがgetElementsByTagNameで
得た配列が返されます。

 注意

すでに他の回答者の方からもご指摘があるように、これはある程度苦肉の策で
前回の回答にも書きましたが「javascriptはこう動いているのか」ということを
理解するための勉強だと思って下さい
実際いまのモダンブラウザはquerySelectorやquerySelectorAllで必要十分な
オブジェクトのつかみ方ができるようになりましたので、今回のような特殊な処理は
よほどのことがなければ出番はありません。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/10/05 16:31

    たくさん書いて頂いてありがとうございます。今からがんばって最読解してみますね。

    キャンセル

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

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

関連した質問

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

  • JavaScript

    15310questions

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