忍者ブログ
プログラマ、ララ・ベル子さんのゆるふわ奮闘記。

[PR]

×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

ES2015のブロックスコープとアロー関数でJSの罠回避

皆さん、こんにちはベル子です。
このブログでコード貼り付けると見た目が悪くて耐えられないので
これからgistを使うことにしました。
デキるレディーはいつもオシャレ。

ということで本題です。
こないだのES2015でうまく説明できなかったfor文で同じ値が参照され続けてしまう罠のサンプルを作成したので、解説しようと思います。
まずは下のコードを見て出力結果を予想してみてください。何が表示されるでしょうか?
これを書いた人が期待しているのは、以下のような出力結果です。

0 hello I'm hanako 
1 hello I'm hanako
2 hello I'm hanako





ですが、実際は以下のように出力されます。
※以下はJS Binでの出力結果です。

3 hello I'm JS Bin Output 
3 hello I'm JS Bin Output
3 hello I'm JS Bin Output





上のコードには2つの問題点があり、それの原因となっているのがjavascriptのスコープです。
スコープというのは「変数が参照できる範囲」のことです。
元々、ES6以前のjavascriptにはブロックスコープがありませんでした。
ブロックスコープというのはif文やfor文の{}で囲まれた範囲内でしか変数を参照できなくさせるスコープのことです。
なので、for文の初期化で定義したカウンタ変数iはfor文の外で定義されたのと、スコープ上は変わりがありません。


var i = 0;
for (i = 0; i < 3; i++) {
setTimeout(function(){
console.log(i + " hello I'm " + this.name);
}, 0);





そしてsetTimeoutの中のコールバック関数には、iという変数の参照を渡しているだけなので、ループが先に実行されて、ループが終わったあとでsetTimeoutの中の関数が実際に実行される際には最後に代入された3を参照してしまうので、期待の結果が得られません。

これをvar i = 0の部分をlet i = 0に置き換えてみると、ループの度に新しいiが定義されて、その新しいiを関数に渡すことになるので、期待どおりにインデックスを出力してくれます。

そしてもう一つはthisの参照先の問題です。
setTimeoutの中のコールバック関数は、setTimeout() が呼び出された関数とは「別の実行コンテキスト内で」実行されてしまうので、結果的にグローバルオブジェクトを参照することになります。

実行コンテキストってなんだよって思うと思うんですが、javascriptは関数を実行するたびに新しい実行コンテキストというものを作成しています。
関数の外にあるコードはどうなるかというとグローバル実行コンテキストというのがあって、グローバルオブジェクトで管理されています。

要するに、setTimeoutのコールバック関数内にthisを書いてしまうと、this=グローバルオブジェクトになるということです。
だから、期待の値が出力されません。
これをアロー関数を使うと、setTimeoutを囲ってる関数の実行コンテキストのthisの値が設定されるようになります。

難しい言い方をしましたがsetTimeoutを囲ってる関数のthisとコールバック内のthisが同じになるということです。

というわけで、ES2015のブロックスコープletとアロー関数を使って書き換えると、
すごく直感的に分かりやすいコードになるというわけです。めでたしめでたし。

拍手[0回]

PR

ES2015関連の英語を日本語に訳しておく

次のPG会のホストは私ベル子です。

参考資料が英語で書いてあることが多いので、スライドを書く際に簡単に日本語に変換できるように、ES2015関連の英語/日本語辞書を作っておこうと思います。

Constant
定数

immutable variable
不変値
Block-Scoped Variables
ブロックスコープ変数

Block-Scoped Functions
ブロックスコープ関数

Arrow Functions
アロー関数

Expression


Statement


Bodies
文体

intuitive
直感的な

Lexical
語彙的な

Parameter Handling
引数操作

Default Parameter Values
デフォルト引数

Rest Parameter
残余引数

Spread Operator
スプレッド演算子

Template Literals
テンプレートリテラル

String Interpolation
文字列補間

Raw String Access

生の文字列にアクセス

Binary & Octal Literal

バイナリ&八進リテラル

Unicode String & RegExp Literal

ユニコード文字列&正規表現リテラル

Property Shorthand

プロパティの省略

Computed Property Names

算出済みプロパティ名

Destructuring Assignment

分割代入

Fail-Soft Destructuring

フェイルソフト分割

Class Definition

クラス定義

Class Inheritance

クラス継承

Iterators

繰返し処理、イテレータ

Collation

照合

Currency Formatting
通貨フォーマット、通貨書式

うーーん。こうやって読み返すと辞書を作るほどでもなかったかな。
引数、演算子、関数とか特定の単語は、英語ではなく日本語で表記する傾向にあるっぽいけど、それ以外はカタカナで当てていけばよさそうです。

個人的にも全てカタカナよりは漢字が混じってるほうが読みやすいので、翻訳する人もそういう部分も意識しているだろうなと思います。

それでは!

拍手[0回]

ViewComposerで渡すデータをControllerで渡したデータとマージする

DOMO、最近、go言語に興味があるベル子です。
速いは正義。

話は変わって、
皆さんは、グローバルなメニューなどで使わなきゃならない値がある場合、
どうしてますか。

私がそれと初めて出くわしたのは、今の会社に入って間もなくのことでした。
グローバルメニューに設置するお知らせ機能で使うデータです。
まだLaravelのこともよく分かっておらず、
毎日Google先生とドキュメントを並べて睨めっこしながら書いていた頃です。
いや、今でもしょっちゅう睨めっこしてますねw

それでどうしよーかなーと思ってStack Overflow先生に聞いてみたら
ViewComposerを使ったらええよって教えてくれました。偉大。
ただ、もうその頃は5がリリースされてたんで5系の記事ばかりで、
4.2と5で何がどう変わったのかもよく知らなかった私は、4.2でどうしたらいいのか困ってしまって、先輩PGに聞いてみることにしました。
そしたら、「そんな難しいことしないでViewで直接取ってきたらいいんじゃないの」と言われて「ああ、確かに」となったわけです。

それで調子に乗って、面倒くさい時はViewから直接、値を取りまくっていたら「こういうのはControllerに書いて」と言われたんですね。
「でもパイセンもユーザーデータはViewで、毎回、取ってるじゃないですか!これと何が違うんですか?!」と言ったら、「これくらいは仕方ないんだよね」との回答で、当時はその理由がよく分かってませんでした。

「仕方ない」を要約するとこうです。
私たちの作ってるようなアプリケーションて、ログインユーザーにいろいろ紐づけられていることが多くて、ログインユーザーデータはしょっちゅう使うことになって、それを毎度毎度Controllerで設定してやるのが面倒だし、そのページのユニークの値でもないからワザワザ毎回書いて渡すのは気持ち悪い。
あとLaravelのFacade使って書けるので、Auth::user()みたいな感じで、めっちゃ短いし、Facadeだから毎回取りにいってるのとは違う。
ということなんですね。

ただ、MultiAuthになるとユーザーデータ取るときにAuth::guard('user')->user()みたいに取らないといけなくて、長くて見た目が気持ち悪いので、今、自分がやってる案件では毎度Viewにwithで渡していたんです。
そしたら一緒に書いているエンジニアさんから「これ毎回渡すの面倒くさいから、ViewComposerで弾込めしてもいいですか?」と言われたんです。
やっぱね、そうだよね。
私も何となくそれがいいんじゃないかと思ってた。

それで、ここからが本題なんですけど、ViewComposer てめっちゃ便利なんですよ。
そのViewで使う値を弾込めしておけるから、Controllerから渡してやる必要がないんで、
「このページでもこの値(view)使ってたんだー。わーマジ面倒いわー。」がなくなります。

しかもViewの指定に以下のようにワイルドカードが使えるので、このディレクトリ以下のView全部に弾込めねーも出来ちゃうという。
View::composer(
'profile/*', 'App\Http\ViewComposers\ProfileComposer'
);


すごいよ、すごいよ。

具体的にはComposerServiceProviderを追加して、そこで弾込めするviewと、ロジックを書くComposerクラスを指定するという感じです。
詳しくはドキュメントを参照。
ServiceProviderを新しく作成したときは、config/app.phpのprovidersに追加するのを忘れずに。

それで、先日、大きなUI改修があって、いろいろ弾込めしないといけない事案が発生。
ViewComposer 使ってなかったら、もうげんなりしちゃうとこですが、そう今の私にはViewComposer があるんだぜっ!
だから全部使いそうな値はこっちに移してやるんだぜっ!

いでよ、超絶コピペ技巧!!
いやーいい汗かいたぜ。

と思ったのもつかの間、他の実装を進めていると、何やらデータがいろいろおかしい。
そしていろいろエラーが出ている。

ちゃんとControllerで設定してあるし、dumpしても値取れてるやん。
Viewでdump。

ファッ!?Controller の値とView の値がちがう。もしや呪いか!?
どうしよう、近くに教会がない。。

と思ったけど、私には思い当たることがあった。
そう、昨日の超絶技巧。
原因はきっとあれや。

あれー?蘭ねーちゃん、でもComposerの値ってController ので上書きされるんじゃなかったっけ?
そう書いてあった気がするんだけどなぁ(メガネキラーン)。

で、ドキュメントを確認したところ、
Just before the view is rendered, the composer's compose method is called with the Illuminate\View\View instance. 

つまり、viewがレンダリングされる直前にcomposeメソッドは呼ばれる。

なんだ書いてあるやん。しかもめっちゃ逆やん。
100万年前からそうだと思ってたけどね!

というわけで、
Controllerでその変数設定してたら、そっちで上書きねーを実現するには、
以下3つの方法のどれかにする必要がある。

・viewのデータをgetDataしてmergeする
・ComposerやめてCreatorにする(Creatorはレンダー直前じゃなくてViewがインスタンス化された直後に実行される)
・offsetExistsで、すでにkeyがあるか判定する

viewのデータをgetDataしてmerge

view()->composer(‘partials.header’, function ($view) {
$with = array_merge([
'message' => 'This is a message on some page'
], $view->getData());
$view->with($with);
});


参考サイト

ComposerやめてCreatorにする

view()->creator('profile', 'App\Http\ViewCreators\ProfileCreator');


参考サイト

offsetExistsで、すでにkeyがあるか判定する

if($view->offsetExists('language_id')) {
$language_id = $view->offsetGet('language_id');
}


参考サイト

今回は設定するデータが多くて、すでにkeyがあるのか判定するのが面倒なので一番上のマージする方法を選択することにした。

ってここまで書いていて思ったんだけど、
ワイルドカード使ってるから同じディレクトリ配下のpartialなviewをいっぱい読み込んでいたら
全View分でデータ取ってきてマージしてってしてそう。。。
やっぱり弾込めするViewは細かく指定したほうが良さそうですね。

週明けにもう一度dumpしながら修正することにしよ。

ということで、皆様も便利なものを使うときは
使用上の注意をよく読み、用法・用量を守って正しくお使い下さい
じゃないと期限日直前に呪われます。

God bless you.

拍手[0回]

HTML5 Conference 2016 に行くよっ!

公式Twitterでもつぶやいたけど、『HTML5 Conference 2016』に行って来ます。

ちなみに関係ないけど、今日は女性が歌う平井堅をyoutubeで聴きながらコーディングしてみたベル子です。いやー女子の声ってホントに癒やされるー。

欅坂46 『サイレントマジョリティー』にハマって聴いていたら、その関連で乃木坂もオススメされて聴くようになって、そのついでに元々大好きなKPOPガールズアイドルも挟みながら聴いていたら、なぜかややセクシーな動画とかもオススメされるようになったので(たぶんJPOPアイドルは関係なく聴いてるKPOPアイドルがセクシーすぎるという噂w)、焦って無理やり平井堅とか洋楽とかRADWIMPSとか織り交ぜながら聴いてみたら、元に戻ってきました。
ふーやれやれyoutubeよ、性別を念視してくれYO。

おっと、話がそれちゃいましたが本題に戻って
「HTML5カンファレンスに行くからみんなで行こうよー」と会社の人々を誘ってみたら、TTパイセン以外の人に華麗にスルーされて、さらにTTパイセンも枠がキャンセル待ちになってたので一人で行くことになったことをここでお知らせしておきます。
一人くらい一緒に行ってくれてもいいと思う。←

というわけで「なるほど、まったくわからん」を回避するため、今更ながらHTML5について下調べしてみることにした。

このセッション一覧の中から、「なるほど、まったくわからん」と、「あーそれね。はいはい聞いたことあります。3年前から知ってMASU」を探していくよ★
(一部、個人的な感想です。)
http://events.html5j.org/conference/2016/9/session/

React
view専用のjsライブラリだよね。知ってるし、使ったことある!

ReactNative
使ったことないけど聞いたことあるよ!
Reactベースでネイティブアプリを作れるSDKかな?

JavaScript Fatigue
初耳w
まあみんなjs(jsフレームワーク)に付き合うのに疲れたよってことだろうね。
そうだろうね。

Service Worker
聞いたことある!けどWeb Workerとの違いがいまいち分かってない。
なんかバックグラウンドでjsが動くみたいなイメージかな。

Progressive Web Apps
初耳。
何かの技術ではなく、よくあるGoogleの布教活動的なあれっぽい。

Push Notification
知ってる知ってる!こないだ調べた!
Webで使えるPush通知だよね。

Offline Cache
Cache APIとか聞いたことあるけど、それのことかな。。。

WAI-ARIA
聞いたこともないから、調べてみたらアクセシビリティの何かの仕様らしい。
アクセシビリティの仕様の読み方が分からないのでアクセシビリティ的にどうかと思う。

Houdini
上のやつより読みにくいよ!W3Cが取り組んでいる新しいCSSの拡張仕様のようだ。
ホウジニかな。。フーディナイかな。フーディーニかな。
フーディーニで変換候補に出てきた!!

WebAssembly
とりあえずQiita様読んでも分からない
http://qiita.com/kenju/items/3ec95aebd30bc95b862c

WebVR

私が狙ってるのはこのセッションだっ!
WebでVRしようよ、ただそれだけ。ゴーグルみたいなの付けて、バーチャルインサニティをリアルで感じようぜ。

WebGL
Webで3Dグラフィックやるやつ。
興味はあるけど何か作ってみたりしたことはない。

A-Frame

WebVRのフレームワークかな。

WebRTC
ウェブでボイチャとかビデチャとかするやつ。
これの実装進んだら自分で好きな仕様のSkypeが簡単につくれるようになるかもね。

Raspberry Pi
手のひらサイズのシングルボードコンピュータ。
最近IoTやりたくて調べてるけど、基本的に電気の知識ないから抵抗とかよく分からなくて難しいなーと思う今日このごろ。

Web Audio
Videoタグの仲間みたいなやつかな?

Web MIDI
上のやつの仲間みたいなやつかな?

Web Bluetooth
これも仲間っぽいよね!

Arduino
OSが積めないほうの手のひらサイズのマイコン。
ラズパイはLinuxOS積んでるからいろいろできるけど、こちらはパソコンにつなげるだけでプログラミングできちゃうという手軽さがあって、いい感じ。

Angular2
噂でよく聞くやつ!いつ頃リリースなんだろう?

Webpack
使ったことある!てんこ盛りのモジュールバンドラー。Laravel 5.3のElixirから標準らしいよ。

Ionic2
聞いたことないけど、フレームワークっぽいよね。

Cordova
聞いたことある。ハイブリッドアプリを作るためのフレームワークみたいなやつだよね。

Unity
実はチュートリアルをやってみたことがある(ドヤ顔)。
簡単に3Dゲームが作れる統合型ゲーム開発環境。
何を隠そうデジハリVFX科を卒業しているので3dsMaxとMayaを使ってみたことがある。という事実を私はひた隠しにしている。
そんな私がデジハリで学んだことは、
「3DCGなんて1年くらいやってみたところで人に見せられるものは何も作れない。」

Material Design
知ってる!Googleが布教してる例のあれ!そしてその宗教に則ったUIが作れるデザインフレームワークのこと。

Atomic Design
上の仲間的な匂いを感じます!

Jobs To Be Done
何だか分からないけど響きがカッコいい。憧れる。

OOUX
もう検索する前から何の略か予想ついて少しにやけてしまうエンジニアあるある。OOで始まったらもうアレしか無い。
そう、みんな大好きオブジェクト指向。

Adobe XD
どうせ新手のアドビツール。


ということで出発前のまとめはこんな感じかな。
どのセッション行こうか迷っちゃうなぁ。

拍手[0回]

Sublime Textでタブ押したらスペ4入るようにする方法

どうも今月の更新頻度がやたら多くなってしまったベル子です。

先日のPG会は「読みやすいコード」についてでした。
そこでこんな話題がありました。

LaravelはPSR-2コーディングガイドライン準拠だから
> インデントには4つのスペースを使用し、タブは使用してはいけません。
とのこと。

ふがっ!!!

以前からtabとspaces4が混在しまくってしまうということがあって(私のコードにw)
気になっていたので先日のPG会のあとにいろいろ調べてみたら、
参考になるページを見つけました。

http://webkaru.net/dev/sublime-text-3-indent/

Sublimeだと

上部メニュー「Sublime Text」→「Preferences」→「Settings - User」で

// インデントの幅
"tab_size": 4,
// タブをスペースに変換
"translate_tabs_to_spaces": true,


を設定してやればいいっぽい。
もうタブなんて絶対入力できなくしてやればいいのである。

さらに、コード全体を切り取って、ショートカットキー「Commnad + Shift + V」で貼り付けるとインデントを反映して貼り付けてくれるそう。便利。
過去のタブも消し去ってしまえばいい。

PHPとかHTMLとかは単にタブかスペースか統一されていなくて
表示する環境によって崩れちゃうだけかもしれないが(それが大問題なんだけど....)
Stylusを書くときは塊のコード内で混在させるとコンパイルエラーが出てしまうので
結構、実害があって嫌だなと思っていたのであります。


でも、いちいちコピペするのは面倒だなーと思って、右下のSpaces:4のところを何気なくクリックしてみたら、「Convert Indentation to Spaces」という魔法のような機能があるではないですか!!


ということで、こんな感じのよくあるタブ&スペース混在のコードを作ってテストしてみます。
選択した状態で、長い棒のほうがタブで、点々のほうがスペースです。

ドン!!



わーすごーい!!
やったーやったよママン。

ということで、これからは気がついたらタブをスペ4に変更していこうかなと思いました。
いきなりいっぱいやると分けわかめなので、少しずつですが。


今までごめんね。他のPGの方。


拍手[1回]