だれも聞いていないと思って歌え

dance as if no one’s watching, sing as if no one’s listening, and live everyday as if it were your last.

Hello World

Hatena Blog 始めました。

プログラマなので技術のことを中心に、月に数回くらい記事を書いていくのが今の目標です。
アウトプットしないのは知的な何とかと言いますし。

簡単に自己紹介をすると、
3年前にPHPを始めてWebプログラミングを始めました。学生の頃はプログラミングは勉強していて、前職では組み込みなど(主にテスター・デバッガーとして)をやっていました。
最近は以前から強く興味のあったJavaScript関連についてよく勉強してます。
フロントエンド見習い(自称)です。

最後に、タイトルにした だれも聞いていないと思って歌えアイルランドのことわざから拝借しました。
自分に足りないものかなと思って、一つの目標として。

Dance as if no one’s watching, sing as if no one’s listening, and live everyday as if it were your last.
だれも見ていないと思って踊れ。だれも聞いていないと思って歌え。あなたが最後の人だと思って、生きろ。
http://rainbowkids.sakura.ne.jp/eigodemeigen.html

webpack を v1 から v2 へ更新してみた

webpack はまだ勉強できていないですが、
webpack 2 が正式リリースされ、更新する機会があったのでその時のメモです。

webpack とは

webpack は WebApp に必要なリソースの依存関係を解決し、アセット(配布物)を生成するビルドツール(要するにコンパイラ)です。
JavaScript だけでなく、CoffeeScript や TypeScript、CSS 系、画像ファイルなどを扱うことができます。
WebApp のビルドツールは Grunt や Gulp が有名です。これらは基本的に、ビルド手順をタスクという形で自ら定義する必要があり、フロントエンド開発に馴染みのない開発者にとっては敷居が高いものでした(少なくとも、自分はそうでした)。
webpack を使えば、Grunt も Gulp も必要ありません!覚えるべきことはほとんどありません。(必要なら)簡単な設定ファイルを書いて webpack コマンドを実行するだけです。
引用: webpack で始めるイマドキのフロントエンド開発 - Qiita

webpack.js.org

参考にしました

webpack-strem を使っていて、 webpack-stream が v2 に対応していないため、新機能の tree-shaking 周りはまだ全く触れていません。

webpack.js.org

stackoverflow.com

また、こちらの記事に変更点などが要約されています。

yosuke-furukawa.hatenablog.com

その他

DedupePlugin

参考サイトを元に修正後、 webpack を実行すると DedupePlugin でエラーが発生しました。 公式ページ内では特に明記されていなかったですが、 Qiita の記事で少し言及されていました。

また、 OccurenceOrderPluginの名前がv2からはOccurrenceOrderPluginに変更、 DedupePluginがなくなるなどがあります。 詳しくはwebpack/releasesのBreaking Changesを探すとわかると思います。

qiita.com

webpack/releases に書かれていることは確認できませんでしたが、 GitHub Issues に経緯などが書かれていました。

github.com

これらを参考に、 DedupePlugin の記述を削除したらエラーが無事取れました!

しかし、コンパイラ後のファイルサイズが大きくなっているものも多く、効果はまだあまり見えていません。。

DeprecationWarning

./node_modules のフォルダを消して、 npm install を実行し直したところ次のような警告が表示されました。

(node:34505) DeprecationWarning: loaderUtils.parseQuery() received a non-string value which can be problematic, see https://github.com/webpack/loader-utils/issues/56
parseQuery() will be replaced with getOptions() in the next major version of loader-utils.

こちらも GitHub Issues に記述がありました。

github.com

どうやら、これは ts-loader などの loader 開発者のための警告だそうです。 webpack2 への移行に伴い仕様が一部変更になり、非推奨となった部分に関して警告が表示されているようです。 (英語の読解力に自信が無いので、ふわっとだけ認識してもらえると助かります)

issue にも書かれていますが( この辺り )、 webpack.js に process.noDeprecation = true; を設定することで警告は除去できました。 ただし、確認するべき警告まで表示されなくなってしまうことを懸念して、業務ではこの設定を行うことはやめました。

技術書の歩き方勉強会「達人プログラマー」編 に行ってきました

11月21日にSpeeさんで開催された技術書の歩き方「達人プログラマー」編に行ってきました。

『達人プログラマー』とは

原著『Pragmatic Programmer, The: From Journeyman to Master』は1999年に出版され、日本では2000年に翻訳されて出版されました。
しばらく絶版となっていたそうですが、今年の10月25日にオーム社から復刊されました。

この本は、ソフトウェア開発の名著として紹介されていることがあるため、タイトルは知っていました。

企画について

以下、connpassからの引用です。

概要

オーム社さんから復刊された『新装版 達人プログラマー 職人から名匠への道』を勝手に応援する企画です。 古典である『達人プログラマー』を今の私たちはどう読んだらいいか、なにを受け取れるか、自分の仕事/キャリアにどう活かしていけるのかといったことについて、お話しする場にできればと思っています。

こんな方におすすめ

プログラマ・ソフトウェア開発者として成長の手引きが欲しいなと感じている方 会社の先輩などから技術書の古典を「読んどけ」と渡されるけれど、うまく読めなくて困っている方 『達人プログラマー』、なんとなく気になっているけれど手を出せていない方 『達人プログラマー』の復刊を応援/お祝いしたい方

『達人プログラマー』というタイトルは知っていても、古典であるというイメージと、初心者が読んでも理解できなさそう・難しそうという思いから手を出せていませんでした。
また、「プログラマ・ソフトウェア開発者として成長の手引きが欲しいなと感じている方」に当てはまったため参加を決めました。

続きを読む

配列の操作(forEach,map,filter,find,some,every)について

何となくで使うのではなく、しっかりと理解しようと思い改めて整理しました。

Array.prototype.forEach()

forEach は、全ての要素に対して関数を一度ずつ実行する。
mapfilter とは異なり新しい配列は生成しない。

// 配列の要素の合計を計算する
let sum = 0;
const list = [10, 20, 30, 40];
list.forEach(param => {
  sum += param;
});

console.log(sum);
> 100

Array.prototype.forEach() - JavaScript | MDN

Array.prototype.map()

map は、全ての要素に対して関数を一度ずつ実行し、返り値(return)からなる新しい配列を生成する。
filter とは異なり、実行対象となる配列の数(before)と、新たに生成された配列の数(after)は変わらない。
また、生成された配列の値には関数実行時の返り値(return)が格納される。

// 配列の全ての要素に10を乗算した配列を返す
const before = [10, 20, 30, 40];
const after = before.map(param => {
  return param * 10;
});

console.log(before);
> [10, 20, 30, 40]
console.log(after);
> [100, 200, 300, 400]

Array.prototype.map() - JavaScript | MDN

Array.prototype.filter()

filter は、全ての要素に対して関数を一度ずつ実行し、戻り値(return)で true を返した要素からなる新しい配列を生成する。
map とは異なり true を返した要素のみの配列を返し、生成された配列の値には実行時の要素の値が格納される。

// 配列の要素が20で割り切れるものだけを抽出する
const before = [10, 20, 30, 40];
const after = before.filter(param => {
  return ((param % 20) === 0);
});

console.log(after);
> [20, 40]

Array.prototype.filter() - JavaScript | MDN

Array.prototype.find()

find は、 true を返す要素が見つかるまで、要素に対して一度ずつ関数を実行する。
true を返した要素の値を返す。

// 配列の要素が20で割り切れるものだけを抽出する
const before = [10, 20, 30, 40];
const after = before.filter(param => {
  return ((param % 20) === 0);
});

console.log(after);
> 20

Array.prototype.find() - JavaScript | MDN

Array.prototype.some()

some は、 true を返す要素が見つかるまで、要素に対して一度ずつ関数を実行する。
true を返す要素が見つかると、 true を返す。

// 要素に一つでも20以上の値があればtrueを返す
const list = [10, 20, 30, 40];
const retVal = list.some(param => {
 console.log(param);
 return (param >= 20);
});
> 10
> 20

console.log(retVal);
> true

Array.prototype.some() - JavaScript | MDN

Array.prototype.every()

every は、false を返す要素が見つかるまで、要素に対して一度ずつ関数を実行する。
false を返す要素が見つかると、 false を返す。

// 要素に一つでも20以下の値があればfalseを返す
const list = [40, 30, 20, 10];
const retVal = list.every(param => {
 console.log(param);
 return (param > 20);
});
> 40
> 30
> 20

console.log(retVal);
> false

Array.prototype.every() - JavaScript | MDN

スプレッド演算子(spread operator)について

上記では配列に対しての操作を例に出しましたが、スプレッド演算子を使うことで配列以外のオブジェクトも同様に処理することが可能となります。

例えば、下記のようなHTML文書のリスト要素からテキストのみの配列を作成しようとする場合はこのようになります。

<div class="sample">
  <ul>
    <li>list1</li>
    <li>list2</li>
    <li>list3</li>
  </ul>
</div>
const elms = document.querySelectorAll('.sample li');
const retVal = [...elms].map(elm => {
 return elm.textContent;
});

console.log(retVal);
> ["list1", "list2", "list3"]

詳しい使い方は Mozilla Developer Network を参照してください。

document.querySelector と document.querySelectorAll について

仕事でよく使っているけど、ちゃんと理解できていなかったので改めて調べてみました。

document.querySelector と document.querySelectorAll

document.querySelectordocument.querySelectorAll とは W3C によって定義された Selectors API の仕様です。 jQuery のようにセレクターを指定して、要素を取得できるメソッドです。

  • document.querySelector … 指定された CSS セレクタにマッチする文書中の最初の要素を返す。
  • document.querySelectorAll … 指定された CSS セレクタにマッチする文書中の要素の全てのリストを返す。

また、同様に文書中の要素を取得するメソッドとして下記があります。

  • document.getElementById … 指定されたIDを持つ要素を返す。
  • document.getElementsByClassName … 指定されたクラス名を持つ要素のリストを返す。

下記のHTML文書を例に、これらの違いについてまとめます。

<div class="news-box">
  <h2>NEWS</h2>
  <ul>
    <li class="news">news title 1</li>
    <li>topic title 2</li>
    <li class="news">news title 3</li>
  </ul>
</div>
<div class="articles-box">
  <h2>ARTICLES</h2>
  <ul>
    <li class="article">article list 1</li>
    <li>article list 2</li>
  </ul>
</div>

要素を一件だけ取得する

NEWSのnewsクラスではないリストの先頭の取得する場合、以下は同じ結果を取得することができます。 document.querySelector を使わない場合、一行で書く方法が分かりませんでした・・・

const elements = document.getElementsByClassName('news-box')[0].getElementsByTagName('li');
let elm = [];
for(var i = 0; i < elements.length; i++) {
  if(elements[i].className !== 'news') {
    elm.push(elements[i]);
  }
}
const element = elm[0];

> <li class="news">news title 1</li>
document.querySelector('.news-box li:not(.news)');

> <li class="news">news title 1</li>

ただし、単発のIDセレクタを指定する場合は document.getElementById の方が高速になります。

要素のリストを取得する

NEWSのnewsクラスのリストを取得する場合、以下は同じ結果を取得することができます。

document.getElementsByClassName('news-box')[0].getElementsByClassName('news');

> [<li class=​"news">​news title 1​</li>​, <li class=​"news">​news title 3​</li>​]
document.querySelectorAll('.news-box .news');

> [<li class=​"news">​news title 1​</li>​, <li class=​"news">​news title 3​</li>​]

こちらも、単発のクラス名を指定する場合は document.getElementsByClassName の方が高速になります。

引数に配列を指定する

ちなみに、引数には配列が指定可能で、 NEWSのnewsクラスのリスト と ARTICLESのarticleクラスのリスト のみを取得することができます。

document.querySelectorAll(['.news-box li.news', '.articles-box li:article']);

> [<li class=​"news">​news title 1​</li>​, <li class=​"news">​news title 3​</li>​, <li class=​"article">​article list 1​</li>​]

CSS セレクタ

これを知っておくと便利だなと思ったものについてまとめました。

:not()

上記例で使っていますが、引数で指定したセレクターの要素を除外します。

document.querySelectorAll('.news-box li:not(.news)');

> [<li>​topic title 2​</li>​]

:first-child, :last-child

:first-child では最初の子要素を取得します。

document.querySelectorAll('.news-box li:first-child');

> [<li class=​"news">​news title 1​</li>​]

ただし、 document.querySelectorAll('.news-box li:not(.news):first-child')擬似クラスを複数組み合わせて使用することはできません(後述します。)

:last-child は最後の子要素を取得できます。

document.querySelectorAll('.news-box li:last-child');

> [<li class=​"news">​news title 3​</li>​]

:nth-child(), :nth-last-child()

引数には子要素のn番目、偶数(even)、奇数(odd)などが指定可能です。

document.querySelectorAll('.news-box li:nth-child(odd)');

> [<li class=​"news">​news title 1​</li>​, <li class=​"news">​news title 3​</li>​]

:nth-last-child() も同様に、最後の子要素から逆向きに数えてn番目、偶数(even)、奇数(odd)と指定できます。

擬似クラスを複数組み合わせる

上にあげた例と同じになりますが、NEWSのnewsクラスを除外したリストの先頭を取得しようと以下のように記述します。

document.querySelectorAll('.news-box li:not(.news):first-child');

> []

しかし、取得対象の :first-child が除外対象の .news であるため空の配列が返ってきます。 :nth-child() を使うか document.querySelector で先頭の一件のみ取得する必要があります。

また、下記のように :not() を複数繋げて使用することも可能です。

document.querySelectorAll('li:not(.news):not(.article)');

> [<li>​topic title 2​</li>​, <li>​article list 2</li>​]

JavaScript勉強中です。 間違いありましたら指摘お願いします。

参考

Moment.jsで日付を扱う

とあるWebアプリを作ろうとしている中で、JavaScriptでもっと日付を楽に扱いたいと調べていて、 Moment.js というライブラリを知りました。

このMoment.jsについて紹介しているサイトは以前からあるので、最近できたものではないです。 比較的最近の Cybozuさんの記事 を読んだのをきっかけに使ってみることにしました。

現在の日付を扱う

Moment.js を参考にダウンロード、もしくはインストールをしてscriptタグで moment.min.js を読み込みます。

// momentオブジェクトの初期化
var today = moment();

// 日付の出力
console.log(today.format());    // -> 2016-06-05T19:37:38+09:00

// フォーマットを指定して出力
console.log(today.format('LLLL'));  // -> Sunday, June 5, 2016 7:54 PM

// 年月日をそれぞれ出力
console.log("year: ", today.year());    // -> year:  2016
console.log("month: ", today.month());  // -> month:  5
console.log("date: ", today.date());    // -> date:  5

moment().month() は、0から11の数字で帰ってくるため6月の場合は 5 と返ってきます。

日本語で出力する

上の手順と同様に、次は moment-with-locales.min.js をscriptタグで読み込みます。 Dateオブジェクトと比較して、この出力フォーマットの指定方法が一番楽だと感じました。

// locale指定
moment.locale('ja');

// momentオブジェクトの初期化
var today = moment();

// フォーマットを指定して出力
console.log(today.format('LLLL'));  // -> 2016年6月5日午後7時54分 日曜日

特定の日付を設定

日付の設定方法はいくつかあります。 moment() と括弧内で指定を行わなかった場合は現在日時で初期化が行われ、逆に括弧内で年月のみ指定された場合は1日で初期が行われます。そのため、上2つと下2つの結果が異なってきます。

// locale指定
moment.locale('ja');

console.log(moment(new Date(2016, 6 -1)).format('LL'));    // -> 2016年6月1日
console.log(moment({year:2016, month:6 -1}).format('LL')); // -> 2016年6月1日
console.log(moment().year(2016).month(6 -1).format('LL')); // -> 2016年6月5日
console.log(moment().set('year',2016).set('month',6 -1).format('LL')); // -> 2016年6月5日

最後に

すべての使い方を把握した訳ではないけれど、便利そうだなと思ったものをいくつか。 これら以外にも多くの関数が用意されている上に、タイムゾーンを扱うこともできるようです(タイムゾーンについては今回触れなかったので省略)。

// locale指定
moment.locale('ja');

// 指定した年月の日数を取得
console.log(moment(new Date(2016, 2 -1)).daysInMonth());  // -> 29

// 1月1日からの経過日数を取得
console.log(moment(new Date(2016, 6 -1, 5)).dayOfYear());  // -> 157

// 1月1日からの何週目か取得
console.log(moment(new Date(2016, 6 -1, 5)).weeksInYear());  // -> 53