とんちむ日記

RubyとJavaScriptと猫が好きです

今さら聞けないJavaScriptのややこしいところ(スコープ、巻き上げ、this)

これはQiitaに昔書いてたやつを引っ越したものです。

①スコープについて

これについては基本なので、ご存知の方は多いと思いますが折角なのでES2015以降の場合も併せて書こうと思います。

変数のスコープはブロックではない(※variable文の場合)

varによって宣言された変数は、通常の{}で作るブロックではスコープを作りません。ifだろうがforだろうが作らないったら作りません。

{
  var a = "foo";
}

if(true){
  var b = "bar";
}

for(var i = 0; i < 1; i++){
  var c = "buz";
}

console.log(a); //=> "foo"
console.log(b); //=> "bar"
console.log(c); //=> "buz"

ではどうしたらスコープを作ることができるのかというと関数定義の{}ならスコープが作られます。

(function(){

  var a = "foo";

})();

console.log(a);
// ReferenceError: a is not defined
  

このように即時関数を最初に記述しておいてその中に処理を記述しているのを見たことがあると思います。ブラウザがJavaScriptのファイルを複数読み込んだ時に宣言した変数や関数が衝突しないように即時関数を使っているんですね。

ES2015以降だとletとconstが使用でき、それによって宣言された変数と定数では関数定義でなくてもブロックでスコープが作られます。

{
  let   a = "foo";
  const B = "bar";
}

console.log(a);
// ReferenceError: a is not defined
console.log(B);
// ReferenceError: B is not defined

BabelやTypeScriptなどでES2015以降の記法が許される環境であればvarによる宣言は使わなくていいでしょうね。

②変数と関数の巻き上げ(ホイスティング)

関数を定義する方法については2種類ありますね。

var func = function(){}; // 関数リテラルの代入

function func(){}; // 関数宣言

この二つですがきちんと使い分けないと思わぬところでハマります。

func(); // TypeError: func is not a function

var func = function(){
  console.log("hello");
};

上の関数リテラルの場合、読み込み時に代入の処理は行われませんから、funcは関数ではないと言われています。呼び出し時はまだundefinedですね。

func(); //=> hello

function func(){
  console.log("hello");
};

対してこちらの例ではfuncの呼び出しに成功しています。 代入などの処理は順に行われますが、宣言についてはそのスコープの最初で行われるからです。これを巻き上げ(ホイスティング)と呼びます。

巻き上げについては変数も同様です。先ほどの関数リテラルの場合のエラーがReferenceError: func is not definedではないことからもわかります。

var a = "foo";

function func(){
  console.log(a); // 1回目
  var a = "bar";
  console.log(a); // 2回目
}

func();

この場合、1回目の出力結果はfooではなくundefinedとなります。funcの最初でaが再度宣言されているためです。上のコードは下のコードのように動作しているわけです。

var a = "foo";

function func(){
  var a; // ここで宣言されている
  console.log(a);
  a = "bar";
  console.log(a);
}

func();

③5つのthis

JavaScriptのthisは状況によって指し示すものが異なります。 その例を見ていきましょう。

1.コンストラクタ呼び出し

function Person(name, age){
  this.name = name;
  this.age  = age;
}

var tom = new Person('tom', 20);

この場合Personのthisは戻り値となるオブジェクトを指します。

2.関数呼び出し

先ほどのPersonを関数として呼び出すとどうでしょう。

Person('hoge', 20);

console.log(window.name); //=> "hoge"

windowオブジェクトにnameというプロパティを追加してしまいました。これからわかることは関数呼び出し時のthisはグローバルオブジェクトを指しているということです。こういった意図しない挙動を防ぐにはstrictモードを使うといいですよ。

function Person(name, age){
  'use strict';
  this.name = name;
  this.age  = age;
}

Person('hoge', 20); //=> TypeError: Cannot set property 'name' of undefined

3.メソッド呼び出し

メソッド呼び出しというのはレシーバのある呼び出し方です。(jsでレシーバという言い方をするのかわかりませんが・・)要はobject.method();といった呼び出し方ですね。

var obj = {
  name: 'obj_name',
  method: function(){ console.log(this.name) }
};

obj.method(); //=> "obj_name"

この場合はobj自身がthisとなります。一番わかりやすい挙動ですねー。

4.applyかcallを使用する場合

Function.prototype.apply()Function.prototype.call()は呼び出し元の関数のthisと引数を置き換えて呼び出すことができるという面白い関数です。

var obj = { name: 'foo' };

function func(){
  console.log(this.name);
}

func.call(obj); //=> "foo"
func.apply(obj); //=> "foo"

関数呼び出しの際はthisはwindowなのでthis.nameundefinedになりそうですが、この例ではthisがwindowからobjに入れ替えられているため呼び出しに成功します。

ちなみに Function.prototype.bind() というのもありますが、これは呼び出し元の関数のthisや引数を置き換えた新しい関数を返すものです。 部分適用した関数を作ることも出来る面白い関数ですよ。(部分適用とよく混同される概念にカリー化というものがあって・・・・・長くなるのでやめます)

5.アロー関数内で定義されたthis

アロー関数はES2015で登場した関数の新しい定義方法です。

function Person(name){
  this.name = name;  
  this.show = () => {
    console.log(this.name)
  }
}

let p1 = new Person("foo");
let p2 = new Person("bar");
p1.show.call(p2); //=> "foo"

このコードの実行結果はp1.show()と呼び出したときと同じです。アロー関数式でのthisは定義するコンテキストのthisに固定されます。なので実行時にthisが変わることがありません。もうbind(this)しなくてもいいんです。 ただし、さきほどのcall(),apply(),bind()で変更することもできません。

おしまい。

Webエンジニアになって4年経った。あと最近転職したよ

いやーまだ四年かーという気もするし、もう四年かーという気もする今日この頃。

多分この記事は推敲あんまりしないし、そもそも文章力がたいしてないので、いつも通りのよくわからん頭悪そうな記事になるかもしれませんが、まぁてきとーに読んでいただけたら嬉しいです。

そう、タイトルの通りWebエンジニアになってから四年経ちました。でも年齢はあれです三十路です。

こういう言い方は「ヘタレだから許してねー」って自分で予防線貼ってる感がすごいあって個人的にはあんまり好きじゃないんですが、いわゆる「未経験からエンジニア」っていうやつです。(と、いいつつ会社の自己紹介に書いた気がする・・)

あと、文系出身ですけどそれで「文系エンジニア」って言うのも好きじゃないです。文系エンジニアってわざわざ自称する人たちが「文系だから英語のドキュメントをスラスラ読めるぜ!」ってんなら何も言うまい。あと僕は英語苦手です(英語のドキュメントは頑張って読みます)

あぁいきなり脱線してしまいましたね・・・。

さて4年前、僕は転職直前までパソコン教室を運営している会社に5年ほどインストラクター兼、教室責任者として勤めていました。ずーっと立ちっぱなしの仕事だったんで「長く続けるのはしんどいなー」と思ったのと毎日そんなに代わり映えしないのが退屈だったのと、週6勤務だったんでもっと休みが欲しかったのと、お金がもっと欲しかったのと、就業規則も見せてくれないくせに社の規定であーだこーだと言ってくるブラックな会社だったのでいつかやめようとはずーと思ってました。

辞める辞めるといいながらズルズル勤めてたら「転職するならするとはっきりしてくれないと困る!」と妻がお尻にガスバーナーで火をつけてくれたので一念発起して転職活動をちゃんとはじめました。

自分には何ができるかよくわからない状態でその時はエンジニアになりたいとはあまり考えてなかったんですが。あるとき、たまたま求人で「未経験でも研修からやります」みたいな 感じのコピーを見つけました。

ちょっとそのときは心躍りました。実は小学生のころはプログラマーになりたかったんですよね、ゲームが作りたかったんです。ゲーム好きな子ってみんなそういう時期あるよね。

高校で絵を始めてから文系に進んでしまったのもあってかずーっとその気持ちを忘れてました。それに世間一般のイメージと同じくエンジニアって理系の情報系の大学出てバリバリやってる人たちがブイブイ言わせてるんだろうとか、未経験だったら無理だろうと思っていましたし。

とりあえず説明会&プログラミング体験会というものをやってたので参加してみます。参加するまで気がつかなかったんですが、その会社は東京の会社でした。当時は大阪在住&新婚だったのでなかなかハードルが高かった・・。でも「引っ越してきてくれたら家賃半額負担するでー」ってありがたい話だったのでそれを交渉材料に妻に相談しました。

妻は悩んではいましたが「日本全国どこでもついていくよ」と言ってくれました。ほんと、マジでこのご恩は一生忘れません。そして無事内定をいただいて、その会社、「株式会社ラクス」のHR事業部(現在は株式会社ラクスパートナーズとして子会社化)に入社することに決めました。

よくSESと混同されがちですが一般派遣です、指揮系統はお客さんです、わかりやすくて良い。

家賃を半額負担してくれるというものの年収はたしか数十万下がりました・・。こっから頑張って取り戻していくんじゃーと研修中は必死で勉強します。当時はJavaを研修の題材にしていて2ヶ月ずっと給料をいただきながら新卒のように研修してもらいました。

が、最初の現場が案件の都合でなぜかしらんけどRuby。「やったことねーよー、営業の無茶振りかよー」と思いつつも日本人が作った言語だというのは高校生くらいからどこかで見かけてずっと知っていたので興味はありました。 最初の現場で結局ほとんどテスターみたいなことを延々やってたんですが、そのうちコードも書くことになるだろうからと同期と一緒に早朝6~7時くらいに出勤してRailsチュートリアルをやってました。お金ないのとからIDEのRubymineじゃなくて不慣れながらもVimでやるという自らハードモードでやってました。

まぁ結局あまり開発をやれなかったのとコードレビューを十数人で対面でギスギスしながらやる胃が痛いスタイルだったので「現場変えたいぜー」と会社に伝えて変えてもらうことに。が、しばらく決まらず・・。で、その時にたまたま上司から「営業先でバカにされたからReactやってみんなに教えたってよ(意訳)」みたいなことを言われたんで暇だったし「jQueryなにそれ美味しいの」くらいJavaScript苦手意識があったのでやってみることに。

当時は確か・・create-react-appが出るちょっと前で、記事も少なかったんだけれどいろいろと調べまくって「npmはなんかgemコマンド+bundler的なやつ」とか「どうやらwebpackというものが必要らしい」とか「ES2015とかいう仕様があるらしい」とか「babelでトランスパイルってことをやる必要がある」とか「Reduxってのがないとバケツリレーがつらいらしい」とか情報の断片をかき集めてなんとか簡易なアプリケーションを作れるくらいにはなりました。JS初心者からまともな教材もなかった(Reactの和書は情報が古かったし、しかも1〜2冊くらいしかなかったと思う)のによくやったなぁと今にしてみれば思います。おかげでJavaScriptはtc39/proposalsのリポジトリをワクワクしながら眺めるくらいには好きになりました。MDNとQiitaとその他いろんなブログに感謝です。

JSの勉強の途中で某大手コンビニチェーン関連のIT事業部の案件があったんですがその上層部がなんかもめたらしくってプロジェクトが一ヶ月で頓挫しました。

でそのうち最後の現場になるBUYMAを運営しているEnigmoさんにアサインされることが決まりました。そのころにはもうだいぶJSどっぷりでRubyというかRails忘れたなーと言う状態だったんですけど、簡単なチケットからちょっとずつやらせてくれてありがたかったです。

結局2年ほどその現場にいることになるんですが、割といろんなことをやらせてもらって設計から実装まで責任持ってやらせてもらえました。派遣だからどうこうってのが、ほとんどなくってみなさん分け隔てなく接してくれました、おかげで当事者意識持ちながらやれてたなぁと思います。

あと仕事が早いフルスタックなエンジニアさんがいて、僕より年齢が一回りも上なのに僕の意見も真摯に聞いて取り入れてくれて「神か!」って感じの人だったんですけど、その方と一緒にチームになった時は正直かなり勉強になりました。デキる人のレビューを受けたりレビューをしたりするのってめっちゃ勉強になります。

で・・そのうちプライベートでは子どもが生まれました。当時はパソコン教室時代の年収は超えてたし、Enigmoさんやラクスパートナーズには特に不満なかったんですが、通勤時間の関係でどうしても妻に育児や家事の負担が偏ってしまっていました。

通勤時間だけでも減らせればその時間で家事や育児ができるかなぁと思ってリモートワークの会社を探し始めます。

と、そんなタイミングで↓の記事がたまたま今の会社の同僚の目に止まったそうです。

tonchix.hatenablog.com

で、RailsGirlsのコーチのつてで連絡をいただき、なんかとんとん拍子に話がすすんで、技術課題もなんとかこなして、今年の2月から「しくみ製作所株式会社」で念願のリモートワーカーとして働いてます。やったね!

リモートワークができるなら年収下がってもいいかなーくらいに思ってたんですがなんと上がりました。月給はあまり変化ないんですが、ラクスパートナーズではボーナスがない給与形態(その分プロジェクトの単価と連動して給与が上がる制度だった)を選択してたので年収はボーナスの分めっちゃ上がりました。わーい。

派遣という身だったせいか自分のスキルに全く自信がなかったんですが、今のチームにはなんとか貢献できているようです。レビューで細かく指摘するせいか「とんちむリンター」と呼ばれることもありました。あとはJavaScriptで苦労した経験もいい感じに貢献に繋がってるきがします。

リモートワークはコミュニケーションが課題になるという話をよく聞きますが、オフィスで仕事してるときよりもかなりコミュニケーション増えました。きっとコミュニケーションを大事にしてる会社やチームだからだと思いますが。リモートだからやりにくいと思ったことはあまりないですね。

きっとこういうことなんだと思います。

今は通勤時間がないので朝(早朝5:30に子どもがのしかかって起こしてくる)から子どもにご飯あげたり遊んだり(無限に絵本を読まされる)保育園に連れていったり、昼やすみにちょっとした家事をやったりと以前よりは協力できてます。今日からは平日も僕がお風呂に入れることになるのでやること増えるけどまぁ可愛いので頑張れる。

プログラマーになる夢は叶えて、リモートワークの夢を叶えたので、次はいろいろと負担をかけてしまった妻に恩返しをしていきたいと思います。

あと子育てで土日忙しいのでリモートで勉強会とかできたらいいなぁと思っている今日この頃。某ねこさんに対抗してnerima.jsとかやろうかなー。

プログラミング初心者へ贈る個人的なググり方

僕がこんなに短いスパンでブログを書くなんてきっと明日は沖縄で雹が降るに違いない。

さて、のっけからこういう話題はアレですが侍エンジニア塾というのがなんか燃えてますね。

まぁそれはそれで別にどうということはないんですが、あそこのプログラミングスクールのブログがうざいとか邪魔だとか色んな話をよく耳にします。

しかし、あのブログそんなに検索に引っかかってくるだろうかと正直なところ疑問に思いました。

もしかして検索の仕方の違い?

これは自分が勝手に根拠も何にもないしそういうマウント的なやつとかじゃなくってほんっと素朴に思っただけなんですが、「初心者と、ある程度経験積んだエンジニアだとググり方が違うのでそもそも初心者向けに書いてある記事は自然に引っかからないんじゃないか」とそう思った次第です。

実際つよそうなエンジニアの方々は侍ナントカをご存知なかった方が多いようでした。(あくまで僕の狭い観測範囲内ですけど)

まぁ侍ナントカが出て来ようが来まいが検索の手段についてよく知っておくことは毒にはならないはずですし、せっかくRailsGirlsTokyoのあとにTwitterで初心者プログラマーのフォロワーも増えたとこなのでそういう記事を書いて手助けできればと思って個人的な方法をいくつか書いてみます。

あくまで個人的なやり方なのでもしかするともっと良い方法あるかもしれませんが良ければ参考にしてください。 もっといい方法があるよーって方はぜひブコメなどに書いていただけると、ありがたや〜と拝んでからこの記事に追記させていただきます。

まずは確認なんですが・・

さて、みなさん標準の検索サイトは何をお使いですか?ググるっていうくらいだからGoogleが多いと思うんですけどBingとかYahooとか使ってる人もいるかもしれないですね。

特に宗教上の理由や、住んでいる地域のしきたりなどがなければGoogleを使うのが無難じゃないかと思います。

公式の検索方法を知る

Google での検索のコツ - Google 検索 ヘルプ

Googleが公式にコツを書いてくれてます。このページにリンクしてある検索演算子とかを知っとけば十分です。免許皆伝です。お主にもう教えることはない、さらばだ!

・・と言うとこの記事の意味がないのでもうちょっと書きます。

エラーが出た時のググり方

プログラマーをやっていてエラーが発生することなく人生を終えられる人は稀でしょう、というかいないでしょう。なのでエラーが出ても慌てない慌てない。むしろ成長の機会を得たと思うくらいにポジティブにいきましょう。

とは言ってもエラーが出た時、初心者のうちは何がなんだかわからずに、さっきまで触っていたソースコードをとりあえず戻してみるとか、ソースコードだけをじーっと眺めるとかやりがちなんですが・・。まずは落ち着いてエラーメッセージを読みましょう。

え?英語がわかんない?大丈夫、割とみんな英語できないから。

そんな時はGoogle翻訳にかければいいじゃないですかー。誰も怒りゃしませんし、恥ずかしいことじゃないですよ。某すごい人なRailsコミッター*1Google翻訳を活用しまくっているそうです。 むしろメソッドや変数の名前を考える時に英語ができなくても翻訳にかけて適切な名前をつけようと努力する人は好感持てます。

まぁ、頻出するような単語の意味くらいは暗記した方がいいですが、心配しなくてもそのうち勝手に覚えていきます。

話が逸れましたね、エラーメッセージをGoogle翻訳にかければ意味がわかって解決するということもありますが、結局なぜそのエラーが発生したかわからない場合もあります。

そんな時はエラーメッセージを検索ワードにしてググりましょう、検索結果の中からできる限り日付の新しいもの(現場で使用している技術によっては古い方がいい場合もあります)を選んでみて行きましょう。ざっと目を通して自分の症例に当てはまるかどうか判断して解決の糸口を見つけて行きます。

時には英語でググろう

日本語で調べても全くわからないし関連記事もない。という場合もよくあります。レアケースや新しい技術ほどよくそうなります。 そんな時は英語でググりましょう。Google翻訳があれば英語の記事も怖くない。中国語がわかる人は中国語でググるのも良いかもしれませんねーVue.jsあたりなんか特に。

〜する方法を調べたい時は how to 〜 と調べると出て来やすいです。ハウツー。

これが動かないんだー!というときは 〜 is not work〜 doesn’t workのように調べます。

英語アレルギーで蕁麻疹が出そうになったら右クリックして「日本語に翻訳」すれば良いです(Chromeの場合)

あとメソッドや変数名を考えたりする時にGoogle翻訳だけでは物足りない場合は synonyms(同意語) antonyms (対義語)とかで調べると良いです。

まぁそうするとだいたいこのサイトが出てくるんで最初からここで調べても良いと思います。 www.thesaurus.com

それから、検索演算子使わなくてもサイト名や言語名を検索ワードに含めることでもある程度絞れます。(当たり前だって思うでしょ?初心者にとっては当たり前とは限らないんですよ)

qiita railsとググればqiitaのrailsの記事にすぐにアクセスできますし、ruby array select のようにすればRubyArray#selectの説明がすぐに出て来ます。

HTMLやJavaScriptCSSなどはMDN Web Docsで調べるのが良いかと思います。

あとブラウザ対応について調べる・・のはまぁ初めは意識しないと思いますがCan I use... Support tables for HTML5, CSS3, etcでJSやCSSの対応状況を調べることもできます。

おしまい

ググる」と関係ないこともたくさん書いたような気がしますが、なんかちょっとテンションがおかしいのと合わせて気にしないでください。多分息子がスーパー早起きで寝不足だからハイになってるだけです。明日読み返して恥ずかしくなってると思います。

*1:誰のことかわからない人は水曜日の22:00過ぎに「すごい人」でTwitter検索してみてください

Rails Girls Tokyoと下心

めちゃくちゃ久しぶりに書きます。もう少しTwitter以外のアウトプットも増やしたい今日この頃。

先日Rails Girls Tokyo 10thにコーチとして初めて参加してきました。とても有意義で楽しいイベントでした。

ぶっちゃけイベントの内容については全然触れてないのでそういうのは期待しないでください(笑)

RailsGirls is 何?

Rails Girlsはより多くの女性がプログラミングに親しみ、アイデアを形にできる技術を身につける手助けをするコミュニティです。

Rails Girls - Japanese より引用

きっかけ

そもそもどうやってこのイベントを知ったの?」という質問を何度かいただいたんですが、Rubyコミッタの柴田さんがTwitterでRaisGirlsTokyoの公式アカウントのツイートをリツイートしていたことで存在を知りました。

そういった訳でイベント自体は以前から知っていたんですが、当時はまだまだ未熟者(今も未熟者ですが)で人に教えられるほどの知識や技術はなかったと思います。また、コーチをやる理由も特になかった気がします。

参加した理由

イベント中に「どうしてコーチとして参加したんですか?」と参加者の一人に質問されることがありました。 なるほど確かに「初心者に教えることでコーチになんのメリットがあるんだろうか?」という疑問は最もです。

理由はコーチによって様々だと思いますが、自分が参加した理由としては「IT業界の労働環境の改善のため」です。

子育てが大変

私事ですが(ブログってそういうのを書くとこだと思いますが)、今年の2月に長男が産まれて今8ヶ月になったところです。

子どもが生まれてからというもの、会社のイベントは基本的に断って、残業も一日に0 〜30分程度で切り上げて、できる限り妻に負担が集中しないように育児を分担している日々が続いています。(それでも通勤時間の関係でいろんな家事育児の負担が妻に偏ってしまっています・・)

息子は世界一可愛いですし、育児は大好きなのでそれ自体は苦痛はないんですが、その分勉強会に参加することができなかったり、仲のよかった同僚の送別会を断ったりするのは中々心苦しいものがあります。

また、社会や行政の子育てに対する支援というのも充分ではないと感じることが多くなりました。

そんな状況になったので現在の「子育てしながら週5日で朝から夜まで働く」ということに強烈な違和感を感じるようになりました。「こんなことは人間のすることじゃない」くらいに思います。

しかも土日もぐうたらゴロゴロできるわけじゃないんです。子育てに休みはないんです。IT業界に限らず異常です、どうかしてます。「今までみんなやってきたんだ当たり前だ」とかいう人がいるかもしれませんがその感覚がどうかしてます。

そしてRailsGirlsTokyoのコーチに

そんな折にRails Grils Tokyo 10thのコーチの募集を見かけました。

ふと「女性エンジニアが増えることでIT業界の労働環境が改善されるのでは」という考えに思い到りました。

何故かって、IT業界は現在深刻な人手不足です。男女問わずエンジニアを欲しています。そのため採用活動にあたって(昨今の働き方改革の風潮もあってか)労働環境の良さをアピールしている企業も少なくありません。

IT業界に女性エンジニアが増えることで、「女性にとって働きやすい環境を整え、女性エンジニアの採用を促進させよう」という動きが出てくると想像できます。というかすでにある程度あると思います。

となると、週3〜4日労働やテレワーク、リモートワーク、ちゃんとした裁量労働制、子どもの看護休暇などの各種制度の導入に繋がるのではないかと思います。

「そういった状況を生む一助になれば自分もいつかその恩恵に与れるだろう」というのが今回コーチとして参加した理由というかまぁ下心です。

タイトルに下心と書いたから出会い求めてとかそういう話だと思っただろう!残念!割と真面目な理由でした!

終わりに

この社会は国や会社もそうですが、我々一人一人の活動によって作られています。ブラック企業も、悪しき慣習や偏見や差別も、「誰か」ではなく我々一人一人のせいで未だに残ってしまっているのだと思います。ですから我々一人一人の行動次第で緩やかにかもしれませんがきっと変えられると思います。

いつか未来の息子に、この社会を形成した者の一人として胸を張ることができるように、これからもRails Girlsやその他の活動に関わっていくつもりです。

・・・

あ、フルリモートワークできる職場探してます。@t_tonchimでTwitterやってるので連絡ください。駆け出しエンジニアの支援もやってます。お気軽にどうぞー。

javascriptのvalidationをchainする

きっかけ

  • いちいちバリデーションする時にif() ~とかするのがめんどくさい。
  • chainでバリデーションを実行したい
  • Railsのvalidationみたいにerrors.full_messagesみたいにまとめてエラーメッセージ取れたら嬉しい

・・と思ってまたライブラリでも作ろうかと思ってたけど調べていたらvalidator.jsのissueにこんなのがあった

var validator = require('validator');

function ValidatorChain(str) {
    this.str = str;
}

Object.keys(validator).forEach(function (fn) {
    ValidatorChain.prototype[fn] = function () {
        var args = Array.prototype.slice.call(arguments);
        args.unshift(this.str);
        if (!validator[fn].apply(validator, args))
            throw Error(fn + ' failed with ' + this.str);
        return this;
    };
});

exports.check = function (str) {
    return new ValidatorChain(str);
};

check('foo@bar.com').isEmail().isLength(5, 64);

引用元: https://github.com/chriso/validator.js/issues/407#issuecomment-118561692

「様々なユースケースに対応するためにあえて標準ではchainできるようにしてない」 みたいなニュアンスの事が書いてあって、上のコードでchainできるようになる。

とはいえこれだとエラーメッセージはカスタマイズしにくいし、chainを全部通してから全部のエラーメッセージを表示するとかってのもできない。あとクライアントサイドなら別にthrowしなくてメッセージだけでいいって事もあるかもしれない。

と思って上に手を入れてこんな感じにしてみた。

import validator from 'validator'
import messages from './messages.js'

function ValidatorChain(str, messages) {
  this.str = str;
  this.errors = [];
  this.messages = messages;
}

Object.keys(validator).forEach(function (fn) {
  ValidatorChain.prototype[fn] = function (...args) {
    args.unshift(this.str);
    if (!validator[fn].apply(validator, args)) {
      const message = this.messages(fn, args)
      this.errors.push(message)
    }
    return this;
  };
});

function check(str, messages) {
  return new ValidatorChain(str, messages);
}

console.log(check('foo', messages).isEmail().isLength(5, 64).errors);

こうすればmessages.jsをこちらで用意すればメッセージをカスタマイズできるし、全てのバリデーションを通した結果の全エラーメッセージを取得できる。

messages.jsは以下のように作る。args[this.str, ...呼び出したvalidatorの引数]という感じになる。

export default function(fn, args){
  const messages = {
    isEmail: `${args[0]}は正しいEmailの形式ではありません`,
    isLength: `${args[1]}文字から${args[2]}文字以下で入力してください`
  }
  return messages[fn]
}

babelでトランスパイルして実行してみた。

$ node build/index.js
=> [ 'fooは正しいEmailの形式ではありません', '5文字から64文字以下で入力してください' ]

errorメッセージの有無でバリデーションの成否を判断するとか、もしくはValidatorChainのプロパティにエラーがあったかの状態を追加すればいいんじゃないかなと思う。

Google Chromeがimportに対応した

対応するって話は知ってはいましたがとうとう対応したんですね。ちょっと興奮して久しぶりにブログを更新してます。

ES2017も正式勧告されたこのご時世にimportを知らないwebエンジニアは少数だと思いますが、使い方はこちら

Safariも最新版はiOSを含めて対応してると小耳に挟んだので他のブラウザ実装状況はどうだろうかとcan i useで調べて見ました。

今のところこんな感じみたいでEdgeやFirefoxもデフォルトでは対応していないもののNot supported by default, but can be enabled. とあるので設定変更するとかで有効にできるようです。

というわけでやってみた。

// hello.js
const Hello = "hello"
export default Hello
// sample.js
import Hello from './hello.js'
console.log(Hello)
<!-- index.html -->
<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="UTF-8">
  <title></title>
</head>
<body>
  <script type="module" src="./sample.js"></script>
</body>
</html>

chromeはローカルのファイルだと制限があるのでpythonのサーバーを立ち上げます。

$ python3 -m http.server

http://localhost:8000/index.htmlchromeで開くと・・ コンソールにhelloと表示されました。やったね!

ちなみにnode_modulesには対応してないのでそういうの使いたければ適当な場所に置いといて読み込むとか、これまで通りWebpackなどのモジュールバンドラーを使う必要があるそうです。

とは言ってもグローバル汚染しなくてもライブラリを扱えるのは素晴らしいです。

他のブラウザも早く対応して欲しいですね。

モック用のJSONやCSVなどのデータを大量にかつ簡単に作成できるMockarooを試してみた

どうも、フロントエンジニアになりたい人です。

js側から叩くAPIがまだサーバーサイドで実装されてないけど、js側の処理も先にやっとかないといけないって状況ありますよね・・多分。僕は今のところ経験したことないけどきっとある。

あと、テスト用のデータ欲しいとか。簡単なjsのデモ作りたいけどそのためにAPIを実装するのも面倒だとか、そもそもサーバーサイド作れないとか。

そこでAPIの仕様さえ決まってれば1000件のデータまで無料でJSONCSVや TSVとかなんならSQLもいけるらしい)ファイルを作ってくれるサービスMockarooを見つけました。

こちらが初期状態です。 f:id:tonchix:20170509161216p:plain

Field NameはDBでいうカラム名ですね。Typeはどういうデータを入れたいかを指定します。ランダムでそれっぽいデータを作って入れてくれます。Fakerっぽいやつだと思って貰えば良いかと。

Optionにあるblankは空(DBでいうとNULL)が入る割合を指定できます。50%だったら1000件作れば500件ほどのデータは指定したフィールドに値がないものになります。

fxは生成されるデータを加工したい場合にここで指定できるようです。用意されている関数を使うこともできますし、Rubyが書けるならRubyを使って加工することもできます。例えばthis.upcaseとやれば全部大文字にするとか。

こんな感じで英語わかんなくてもぱっと見た感じ簡単に作れそうですよね。 でもちょっとだけ悩んだのが、こういうデータが欲しい時。

{
  "friends": [
    { "first_name": "foo", "last_name": "bar" },
    { "first_name": "hoge", "last_name": "huga" }
  ]
{

以下のようにすれば良いみたいです。

f:id:tonchix:20170509155905p:plain

↓こういうのが欲しい場合は 上の例からJSON Arrayのフィールドを無くせば良いです。

{
  "friends": {
    "first_name": "foo",
    "last_name": "bar"
  }
}

また、単純な配列が欲しいだけならば、フィールド名[2]とかやると[]の中で指定した大きさの配列になります。

あとはダウンロードして適当なところに置いてjsから呼び出せばOK!やったー。しかも無料の範囲なら登録不要みたいですよ、楽ですねー。

他にも公式のnpm packageもあってこちらはAPIkeyが必要なので登録する必要がありますが、無料プランだと1日200リクエストまで使えます。詳細はリンク先をみてもらえればなんとなく雰囲気掴めると思います。

実際に試してみました。下のようにclient.generateとすればPromiseを返してくれるようです。generateに渡すcountの値が1の場合はPromiseから取り出す値は配列ではないので注意してください。

const Mockaroo = require('mockaroo');

const client = new Mockaroo.Client({
  apiKey: '******' //自分のAPIKeyを入れてね
});

client.generate({
  count: 10,
  fields: [{
    name: 'id',
    type: 'Row Number'
  },{
    name: 'friends.first_name',
    type: 'First Name'
  },{
    name: 'friends.last_name',
    type: 'Last Name'
  }]
}).then(records => {
  for(let record of records){
    console.log(record.id, record.friends.first_name, record.friends.last_name);
  }
    console.log(records[0]);
});

結果は以下のようになります。(最後のはちょっと整形してます)

1 'Susy' 'Ingarfill'
2 'Jakob' 'Duligal'
3 'Lanie' 'Jamieson'
4 'Joanna' 'Betham'
5 'Magdalena' 'Castledine'
6 'Roxine' 'Cogdon'
7 'Bea' 'Trevaskis'
8 'Gertruda' 'Bannard'
9 'Dorelle' 'Moors'
10 'Bruno' 'Dorot'
{ 
  id: 1,
  friends: { 
    first_name: 'Ermin',
    last_name: 'Rosenfarb'
  }
}

簡単だし便利ですねー。

ただ日本語対応してないっぽいので日本語のデータ欲しいならばfxのとこで無理やり日本語データ作るか、これじゃなくてFakerとか使うかする必要がありますね。

サイトではSQLも作れるのでDBにテストデータを作るのにも便利だなーと思いました。僕はRailsを主に使うのでその辺の必要性はないですが、データを作るのが面倒な開発環境ならそこそこ使えるかも知れませんね。

もっといい方法あるよーって場合はぜひ教えてください。