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

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

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

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

Q&A

解決済

2回答

271閲覧

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

takane

総合スコア63

JavaScript

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

0グッド

0クリップ

投稿2017/10/05 06:38

編集2017/10/05 06:45

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

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

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

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

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

js

1<script> 2HTMLCollection.prototype.getElementsByTagName=function(i){ 3 var ret=[]; 4 Array.prototype.map.call(this,function(j){ 5 Array.prototype.push.apply(ret, Array.prototype.map.call(j.getElementsByTagName(i),function(k){ 6 return k; 7 })); 8 }); 9 return ret; 10}; 11window.onload=function(){ 12var touchList = document.getElementById('aplication').getElementsByTagName('li').getElementsByTagName('img'); 13console.dir(touchList); 14} 15</script> 16<ul id="aplication"> 17<li>test1</li> 18<li><img src="test2.jpg" alt="test2"></li> 19<li><img src="test3.jpg" alt="test3"></li> 20<li><img src="test4.jpg" alt="test4"><img src="test5.jpg" alt="test5"></li> 21<li>test6</li> 22</ul> 23<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で調べてもいまいちよくわかりません・・・

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

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

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

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

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

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

m.ts10806

2017/10/05 06:50

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

2017/10/05 06:51

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

2017/10/05 07:04

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

回答2

0

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 06:56

編集2017/10/05 07:03
maisumakun

総合スコア145121

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

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

takane

2017/10/05 07:25

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

0

ベストアンサー

解説

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

まず、通常の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 07:29

yambejp

総合スコア114581

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

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

takane

2017/10/05 07:31

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問