##JSの問題集、コード書く練習になるものオススメのものがあればおしえてださい。
こんにちは、JS初心者です。
JSの基礎、変数、配列、DOM操作は理解しております、(完璧ではないです)
その上で、現在jQueryを学んでいます。
最近思うことは、どうしても冗長なコードになってしまいがちです。
もっとスマートにかけるようになりたい!
勉強不足な面もありますので、
もっと数をこなしたいとおもいました!
問題集などあれば、
みなさんがスマートにかけるようになった方法などあれば教えて頂きたいです。
知恵袋的な場にしてしまい、申し訳ありません。。。。
例コード
$(function(){ $('.js-hoge > li > a:eq(0)').on('click',function(){ $('.js-hoge0').fadeIn(); $('.hoge1, .hoge2, .hoge3').fadeOut(); }); $('.js-hoge > li > a:eq(1)').on('click',function(){ $('.hoge1').fadeIn(); $('.hoge0, .hoge2, .hoge3').fadeOut(); }); $('.js-hoge > li > a:eq(2)').on('click',function(){ $('.hoge2').fadeIn(); $('.hoge1, .hoge0, .hoge3').fadeOut(); }); $('.js-hoge > li > a:eq(3)').on('click',function(){ $('.hoge3').fadeIn(); $('.hoge0, .hoge1, .hoge2').fadeOut(); }); });
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/10/24 07:07
2017/10/24 07:36
2017/11/05 13:15
回答6件
0
最近思うことは、どうしても冗長なコードになってしまいがちです。
これは単に心がけの問題では?
自分で冗長だと思う糞コードを納品したのに、
私は本業Webデザイナーorコーダーだから、
JavaScript初心者だからと逃げ道作ってるだけなのでは?
でもまぁ、そこに自分で気がついて成長したい、何とかしたいと気付けた時点で
何十人に1人の天才だと思いますよ。
私なんて偉そうに語っておきながら先輩に指摘されて初めて気がついた事が山ほどありますからね。
もっと数をこなしたいとおもいました
他の回答者さんが色々問題集を用意してくださっているので割愛
みなさんがスマートにかけるようになった方法などあれば教えて頂きたいです。
ただ数をこなすだけでは昨日までの二の舞でしょう。
というわけで、プログラミング力を上達させる上での鉄則というか縛りを共有します。
- コピペはするな
- 人に説明できない関数やコードの動作はコンソールで全て確認しろ
- for文、関数、リスト操作を駆使して重複を徹底的になくせ
- 行数を抑えろ、ただし1行が複雑になりすぎてはいけない
どれも守っているだけで飛躍的にスキルが伸びる鉄則ばかりで、
JavaScriptに限らずプログラミングスキルに優れた人はこの中の3〜4個を常に守っているように思います。
しかし、初心者の内からいきなり全部守ると死ねるので、
まずはこの中の1〜2個を意識するところから始めましょう。
おすすめは下記2つです。
- 人に説明できない関数やコードの動作はコンソールで全て確認しろ
- for文、関数、リスト操作を駆使して重複を徹底的になくせ
以下4つの鉄則の説明をして〆ます
- コピペはするな
人はコピペすることで妥協します。
JavaScriptにはfor文や関数があるので、
コピペなんかなくても何十回という繰り返しを簡単に表現できます。
コピペを禁止することで、繰り返しを避ける為にどうプログラミングすればいいか頭を使うようになります。
考えないおバカさんは一生コピペで妥協するので考えて考えて考えぬいてください。
思いつかなくても大丈夫、その後にシャワーでも浴びてる間に閃きます。
この時に初めて力になるものです。
この辺は内部モデルの話で、出来ないストレスを頭に与えながら考え続けると成長します。
- 人に説明できない関数やコードの動作はコンソールで全て確認しろ
JavaScriptは最高の環境です。
ChromeならF12でコンソールを開いてコードをペチペチ叩いてEnterキー押すだけで動作を確認出来ます。
MDNやQiita、個人のブログに掲載されているソースコードをベタッと貼り付けるのは三流。
一流のエンジニアは動作を他人に説明出来ないなと思った瞬間打ち込んで確認しています。
頭が良い医者に秘訣を聞くと、普段から肌身離さず電子辞書を持ち歩いて、分からない事があればすぐに調べるというエピソードを聞いた事がありますが、まさにそれと同じです。
- for文、関数、リスト操作を駆使して重複を徹底的になくせ
これは方法論です。
特に配列を作って一気に片付ける方法は絶対に押さえてください。
先日の質問の私の回答を参照。
あれはDOMツリーに手を加えず、元の書き方を腕力のみで改良して片付けている典型的なサンプルで、
[0, 1, 2, 3]
と2
という数値を使って".hoge0, .hoge1, .hoge3"
という文字列作れてるのが確認出来ます。
この".hoge0, .hoge1, .hoge3"
をどうやって作れば良いんだというのがプログラミングのスキルです。
MDNのArray.prototype.map()を始めとする、配列のメソッド達は工夫の宝庫です。
for文を殆ど使う必要がなくなります(実行速度が遅い等のパフォーマンス改善の場面では必要に応じて使いますが)。
- 行数を抑えろ、ただし1行が複雑になりすぎてはいけない
上記3項目と多少ずつ被ります。
ソースコードは英語と数学の中間みたいなルールで書かれている文章です。
つまり、読み手は機械と人間です。
読みやすい文章を書く事が最終的なゴールになります。
難しいことを、簡単にやるのが一流
難しいことを、難しいままやるのが二流
簡単なことを、難しくやるのが三流
同じ難しいことなら、出来るだけ簡単に読めるように書くのが最終的なゴールとなります。
さじ加減はリーダブルコードを立ち読みするのがおすすめです。
ベストセラーなんで、そこそこ大きな書店に入れば大抵置いてあります。
投稿2017/10/24 08:54
総合スコア21158
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/11/05 12:53
0
例コードをまとめて書けるだろうと思えるなら
あとはその方法を見つけるのみでしょう
配列関連の関数を把握しておくと
同じような処理を何度も書くことを避けられるようになります
jqueryならばfilterメソッドを使いこなすと
色々と効率的にかけるようになるかと思います
filterはforeachと同じように使えるのと同時に
絞り込みをかけた要素群を利用して続きの処理を書く事ができるので
filterの使用によって要素の検索処理を合理化できるケースが多いです
例コードも結構filterがハマるかもしれません
効率的にかけるようになるには
やはりそういうコードを多く見る事だと思います
世に出回っているメジャーなライブラリは
時としてトリッキーな記法も用いてコードを効率化していたりします
とりあえず手近なライブラリのコードを追って見るのみ良いかもしれません
投稿2017/10/24 08:04
総合スコア7804
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
原因
JSの基礎、変数、配列、DOM操作は理解しております、(完璧ではないです)
その辺りを理解しているのであれば、基礎的な知識はあるのだと思います。
こういうケースで原因として考えられるものは二つあります。
- 知識はあるが、その知識を引き出せない
- 知識はあるが、一つ一つの知識を組み合わせて、新たなものを創造できない
「プログラミングはパズルのようなもの」と例えられることがありますが、自身が持っている知識をパズルのように組み合わせて作るイメージが私の中にもあります。
この場合、必要になるのは「知識」ではなく、
- 知識を上手く引き出す方法
- 知識を上手く組み合わせる考え方
になる為、問題集で解決できる問題ではないと思います。
手っ取り早い方法としてはデザインパターンの本を読んで、「コードの雛形を全て暗記する」という方法がありますが、教科書通りのコードだけを使っていると、新たな着想を得て自分のコードを書くことが出来なくなるので、私としては自分で考え方を見出す方法を推奨します。
DRY (Don't repeat yourself)
最近思うことは、どうしても冗長なコードになってしまいがちです。
そのコードが冗長とまでは認識しているようですが、具体的に「コードのどの部分が冗長か」まで考えたことはあるでしょうか。
**DRY(同じ事を繰り返すな)**の原則にある通り、「同じコードを何度も繰り返すコード」が冗長なコードです。
従って、「実際に繰り返されているコード」を探せば、改善点が見つかります。
JavaScript
1$(function(){ 2 $('.js-hoge > li > a:eq(0)').on('click',function(){ 3 $('.js-hoge0').fadeIn(); 4 $('.hoge1, .hoge2, .hoge3').fadeOut(); 5 }); 6 7 $('.js-hoge > li > a:eq(1)').on('click',function(){ 8 $('.hoge1').fadeIn(); 9 $('.hoge0, .hoge2, .hoge3').fadeOut(); 10 }); 11 12 $('.js-hoge > li > a:eq(2)').on('click',function(){ 13 $('.hoge2').fadeIn(); 14 $('.hoge1, .hoge0, .hoge3').fadeOut(); 15 }); 16 17 $('.js-hoge > li > a:eq(3)').on('click',function(){ 18 $('.hoge3').fadeIn(); 19 $('.hoge0, .hoge1, .hoge2').fadeOut(); 20 }); 21});
このコード上で「繰り返されているコード」は次の4箇所です。
($('.js-hoge0').fadeIn()
は他とclass名が異なる為、$('.hoge0').fadeIn()
が正しい、と仮定します)
$('.js-hoge > li > a:eq(0)')
(:eq()
のindex値は異なる).on('click',function(){}
$('.hoge0').fadeIn()
(.hoge0
のindex値は異なる)$('.hoge0, .hoge1, .hoge2').fadeOut();
(.hoge0
のindex値は異なる)
「繰り返されているコード」から「繰り返されないコード」にするには大別して、二つの対処法があります。
for
文などの反復処理と配列を組み合わせて、反復させる- 共通処理を関数に追い出してから、関数呼び出し
※ただし、これらは対処療法であり、これだけでスマートなコードが書けるわけではありません。
設計面から見直した方が良いケースもあります。
DRY (同じコードを繰り返し書くな)
前節の方法に従って修正すると、次のように書けます。
HTML
1<ul class="js-hoge"> 2 <li> 3 <a href="#">hoge0</a> 4 <a href="#">hoge1</a> 5 <a href="#">hoge2</a> 6 </li> 7</ul> 8 9<p class="hoge0">hoge0 contents</p> 10<p class="hoge1">hoge1 contents</p> 11<p class="hoge2">hoge2 contents</p> 12 13<script> 14'use strict'; 15jQuery(function (jQuery) { 16 for (let i = 0, classTokens = []; i < 3; ++i) { 17 classTokens.push('.hoge' + i); 18 19 jQuery('.js-hoge > li > a:eq(' + i + ')').on('click', function () { 20 jQuery('.hoge' + i).fadeIn(); 21 jQuery(classTokens.filter(c => c !== '.hoge' + i).join()).fadeOut(); 22 }); 23 } 24}); 25</script>
このコードは関数式を3回使って同じ関数オブジェクトを3回生成しており、**「DRY(同じ関数オブジェクトを繰り返し生成するな)」**の原則に違反している為、次のように修正します。
JavaScript
1'use strict'; 2jQuery(function (jQuery) { 3 function handleClick (event) { 4 var data = event.data, 5 className = '.hoge' + data.i; 6 7 jQuery(className).fadeIn(); 8 jQuery(data.classTokens.filter(c => c !== className).join()).fadeOut(); 9 } 10 11 for (let i = 0, classTokens = []; i < 3; ++i) { 12 classTokens.push('.hoge' + i); 13 14 jQuery('.js-hoge > li > a:eq(' + i + ')').on('click', {i: i, classTokens: classTokens}, handleClick); 15 } 16});
関数を外に追い出した影響で i
, classTokens
が変数スコープ外になってしまった為、event.data
で渡しています。
.filter()
部分でも click
イベントハンドラが発火する度にアロー関数式を生成していますが、GC(ガベージコレクション)で回収される範疇なので、ここではそのままとしました。
パフォーマンス的観点でDRY(同じ関数オブジェクトを繰り返し生成するな)を貫くのであれば、ここもコールバック関数を外へ追い出してキャッシュしたり、関数を生成しない for
文などで書くべきですが、余談なのでここでは置いておきます。
DRY (同じイベントを繰り返し定義するな)
前節のコードではイベントを3回定義しましたが、実は1回で済みます。
jQuery では DOM Events の世界でイベントを定義しており、イベントバブリングという機構によって、親ノードへイベントが伝播している為、親ノードでイベントを捕まえれば良いのです。
JavaScript
1<ul class="js-hoge"> 2 <li> 3 <a href="#" data-i="0">hoge0</a> 4 <a href="#" data-i="1">hoge1</a> 5 <a href="#" data-i="2">hoge2</a> 6 </li> 7</ul> 8 9<p class="hoge0">hoge0 contents</p> 10<p class="hoge1">hoge1 contents</p> 11<p class="hoge2">hoge2 contents</p> 12 13<script> 14'use strict'; 15jQuery(function (jQuery) { 16 function handleClick (event) { 17 var a = event.target, 18 currentIndex = +a.getAttribute('data-i'), 19 classTokens = []; 20 21 for (var i = 0, len = a.parentNode.children.length; i < len; ++i) { 22 if (currentIndex !== i) { 23 classTokens.push('.hoge' + i); 24 } 25 } 26 27 jQuery('.hoge' + currentIndex).fadeIn(); 28 jQuery(classTokens.join()).fadeOut(); 29 } 30 31 jQuery('.js-hoge > li').on('click', 'a', handleClick); 32});
この書き方によって、コード制作者はHTML上でコンテンツを増やしてもJavaScriptコードに修正を加える必要がなくなりました。
コンテンツを追加する際には、<a href="#" data-i="3">hoge3</a>
と <p class="hoge3">hoge3 contents</p>
を追加すればよく、JavaScriptコードを変更する必要はありません。
保守性が向上しています。
DRY (同じような名前のclass名を繰り返し定義するな)
前節のコードでは、.fadeOut()
の対象ノード群の class セレクタを生成する為に面倒な処理が必要でした。
これはHTML上のclass名にindex値を含めている事が原因で、class名にindex値を含めなければ、もっとスマートに書けます。
HTML
1<ul class="js-hoge"> 2 <li> 3 <a href="#" data-i="0">hoge0</a> 4 <a href="#" data-i="1">hoge1</a> 5 <a href="#" data-i="2">hoge2</a> 6 </li> 7</ul> 8 9<p class="hoge" data-i="0">hoge[0] contents</p> 10<p class="hoge" data-i="1">hoge[1] contents</p> 11<p class="hoge" data-i="2">hoge[2] contents</p> 12 13<script> 14'use strict'; 15jQuery(function (jQuery) { 16 function handleClick (event) { 17 var currentIndex = event.target.getAttribute('data-i'); 18 19 jQuery('.hoge[data-i="' + currentIndex + '"]').fadeIn(); 20 jQuery('.hoge:not([data-i="' + currentIndex + '"])').fadeOut(); 21 } 22 23 jQuery('.js-hoge > li').on('click', 'a', handleClick); 24});
原理を解釈する重要性
ここまでコードの改善案を書いてきましたが、私がいいたいことは「この改善案を使ってコードを改善して下さい」という事ではありません。
勿論、紹介したコードは全て私が良いと判断したコードですが、コードの外側だけを読んで「良いコードの参考例」として読まないでほしいと思っています。
「イディオム」や「デザインパターン」のコードを有難がって、そのコードだけを書いていく人をたまに見かけますが、重要なのはそのコードが持つ**「原理」と「原理を応用する考え方」**であって、コードは結果に過ぎません。
例えば、「グローバルスコープ上にコードを書くとグローバル汚染が起きるので、次のイディオムを使ってコードを書きましょう」という説明があったとします。
JavaScript
1(function () { 2 // ここにコードを書きましょう 3}());
結果としてはその通りですが、そこにはこのコードが持つ原理/説明が抜けています。
「とりあえず、このコードを使えばグローバル汚染が防げる」という結果だけを持って満足してしまった場合、理解に乏しい為、知識を組み合わせて応用する事が出来なくなってしまいます。
これは「原因」の節で述べた「知識はあるが、一つ一つの知識を組み合わせて、新たなものを創造できない」の状態ではありません。
「知識がないから引き出すことが出来ない」のです。
原理を理解する重要性を知っている人は、未知の「イディオム」や「デザインパターン」を読んだ時、「こんな書き方があるのか!」とは思いません。
「これはどういう原理で動いているんだ?...(調査後)...なるほど。このコードは~の原理を利用して動いているのか。この組み合わせは覚えておこう。」のように考えます。
それを踏まえて、私がいいたいことは「DRY の原理を理解すること」です。
DRYを知った当時の私は衝撃を受けました。
とても簡単な原理ですが、だからこそ応用範囲の広い考え方だと思います。
私が考えたDRYの応用法は概ね説明していますが、他の場面でもDRYの原理を応用できる場面はあるでしょう。
ですので、yuyuuyu さんご自身でも DRY を応用できないか、考えてみて下さい。
それによって、冗長なコードを書く状況は大きく減ると私は思います。
あと、これまで説明してきた中で、yuyuuyu さんが知らないかもしれない原理に「イベントバブリング」があります。
これについては、uhyohyo.netが詳しいです。
他にも知らない原理があれば、積極的に学んでみて下さい。
jQuery は公式リファレンスが詳しく、日本語の資料(個人サイト)では触りしか書いてない事が多々あります。
Re: yuyuuyu さん
投稿2017/11/05 12:11
編集2017/11/05 12:15総合スコア18164
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/11/05 12:24 編集
0
MDN web docs
のチュートリアルとリファレンスの内容を理解していけば確実にスマートに書ける様になります。
jquery だったらセレクタとメソッドを覚えてください あと this の使い方を覚えてください
メソッドとセレクタをちゃんと覚えればだいぶスマートに書けると思います
投稿2017/10/24 07:19
編集2017/10/24 09:00総合スコア158
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
少し調べたらこんなサイトがあったので、ちょうどいいものがあるか見てみてください。
https://career.levtech.jp/guide/knowhow/article/53/
投稿2017/10/24 07:11
総合スコア928
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。