sessionStorage使ってみた

こんばんは、有村です。
今日のテーマは、sessionStorage使ってみたです!

sessionStrageってなに?という疑問については、
我らがMDN様のリンクを。

さっそくサンプルコード!

一度ボタンを押すと、リロードしても「メッセージ切り替え済み」に表示が切り替わるようになっています!
バナー表示などの切り替えに応用できそうですね!

ただsessionStrageは、タブやブラウザを閉じると消去されるのが注意点です。
「ユーザが非表示ボタンをクリックしたら、未来永劫ずーっとバナーを非表示にしておきたいな…」という実装には向きません><

それでは、きょうはこのへんで。

mouseoverとmouseenterの違いって?

こんばんは、有村です!
あけましておめでとうございます。
2018年も、実装にて気付いたことや引っかかったこと、備忘録としてゆる〜く更新していこうと思うので、よろしくお願いします。

さて、今回はmouseoverとmouseenterの違いって?です!
癖でmouseenterって書くようにはしているんですけど、この両者の違いって明確にはなんだっけ…と分からなくなったので、
調べることにしました!

こんなコードがあったとします。
mouseoverもmouseenterも、どちらもdivに対して設定されていますね!

私はこう思いました…
ログが出力されるタイミングは、どっちも同じじゃないか?と。

しかし、実際にやってみると…
divエリアにマウスが入る → mouseover、mouseenterが反応する
aエリアにマウスが入る → mouseoverが反応する
aエリアを離れる(見た目としてはdivエリアに入る) → mouseoverが反応する
という全然違う結果になりました。

でも考えてみるとおかしい…自分はdivエリアに対してイベントを設定しているのに、なぜaに関するイベントを拾っているのか?
彼らは親と子の関係ではあるけれど、なぜ………………はっ。
バブリングか!?
なるほど、aの要素にマウスが乗ると、そのイベントがdivにも伝搬している…いうことですね。

ではmouseenterの場合はそうではないということでしょうか…
と思って調べました。
https://developer.mozilla.org/ja/docs/Web/Events/mouseenter
我らが守護神のひとり、MDN様はこうおっしゃっています。

Similar to mouseover, it differs in that it doesn’t bubble and that it isn’t sent when the pointer is moved from one of its descendants’ physical space to its own physical space.

残念ながら日本語訳がなかったのですが、なんとなくmouseenterはバブリングしないということが読み取れます。
また、子孫から自身にポインタが移動したときにはイベントが発生しない、という点もmouseoverとの違いですね!
(訳間違ってたらすみません;)
だから「aエリアを離れる(見た目としてはdivエリアに入る)」の場合、mouseoverしか反応しなかったんですね。
納得。

活用シーンを考えると、mouseenter一択じゃないか!?と思ったのですが、

With deep hierarchies, the amount of mouseenter events sent can be quite huge and cause significant performance problems. In such cases, it is better to listen for mouseover events.

とあるので、これまた使い所は考えたほうがいいということですね!

それでは、きょうはこのへんで。

thisを出力してみた

こんばんは、有村です!
今回はふと気になったのでこれを実践してみました!!

thisを出力してみた

です!
よくJSerの先輩から、「thisがそいつ自身を指すのはjQueryだから」と聞いていましたが、
じゃあjQueryではない生のJavaScriptだと何を指すんだろう…と疑問に思った次第です。

ただ、「どういう仕組みなん?」というところまでは理解が追いつかなかったので、
そこに関しては全く意味をなさない記事だと思います…。あくまで備忘録で。

さっそく実践。

その結果はというと…

わー!Windowって出た!
window…グローバルオブジェクトですね。
「これ」を指すのだから、「hoge」自身が返ってくると予想したのですが…(jQuery信者)

じゃあこういったケースはどうなるんでしょうか…

実行すると、なんと!!

と出ます!
thisの向き先が変わりました!!

なんとな〜く、こういうこと?と感覚で掴んでいることとしては、
hogeはグローバル(window)に属していて、fugaはインスタンスとして作成された時点でhogeに属しているのかな?
thisはその属しているものを向き先として設定されているのかな?という。

調べてみると、プロトタイプあたりとも密接に関係してそうなので、それはそれで後日ちゃんと理解したいです。

なんだか感覚値が高い記事になってしまいましたが、備忘録ということで(2回目)
それでは、きょうはこのへんで。

クロージャって何ができるの?

こんばんは、有村です!
前口上が思いつかないのでそのまま本題に入ります!

今回のテーマは、
クロージャって何ができるの?
です!!

なんとな〜く言葉は知っていても、「こう使う!」「ここで使う!」という実践方法が分からなかったので、
今回まとめてみることにしました。

まず例を。

(分かりやすいようにscriptタグを分割しています)
ほげ2を実行すると、何度押しても2・2・2・2……とアラートが出るのですが、
ほげ1を実行すると、押すたびに2・3・4・5……と1つずつ数字が進んでいくんです!

ぱっと見では「hogeを呼んでるけど、結果としてfugaを実行している」という点は変わらないですよね…。
ただ、前者は
関数fugaをreturnで返している
関数hogeを変数に格納している
関数hogeを格納した変数を実行している
という点に違いがあります!

なんでそうなるねんは置いておいて、この記述をすることによって、
通常の記述では保持しないはずのローカル変数「no」の状態(=数)を閉じ込めておくことができるのです!

どのような場面で使うか考えると、カウンタ系とかでしょうか。
「いま◯回クリックしましたよ」とか。
もっと見る機能など、クリック回数をキーとするものに対して有効に使えそうです。

しかし、ローカル変数をそのまま閉じ込めておけるということは、その分変数を保持するためのメモリを割いているということになります。
(通常であればガベージコレクションで破棄される)
昨今の環境では使えるメモリも増えているので大した問題にはならないと思うのですが、
「メモリ領域を食ってるんだぞ〜」という点は覚えておくに越したことはないかなと!

それでは、きょうはこのへんで。

小ネタ2つ!transitionendと暗黙のsubmit

こんばんは、有村です。2ヶ月なにも書いてなかった。
MacBook Proを破格で譲ってもらったので、せめてMacを使って何かをせねば…とブログ書くことにしました(?)

今回は小ネタ2つ。

小ネタ1・transitionendってバブリングするんだ!?
親もアニメーションするし、子もアニメーションする、というコードを書いていました。
(だいぶ略してますが)

さらに、animation1には、アニメーションが終わったタイミングで発火するnanikasuruを仕込んでいます。

で、動かしてみると、なぜか意図しないタイミングでnanikasuruが実行されるんですよね。
なんでだ?どこだ?と調べると、ちょうどanimation2のアニメーションが終わった後でした。

animation2には何も仕込んでないのにな……と思ったものの、それがよくなかった!
なぜなら、transitionendはバブリングするから…!

つまり、animation2のtransitionendがバブリングしてanimation1まで伝わり、
animation1のtransitionendが発火してしまったということですね!

これを仕込まないといけなかった。ここにだいぶやられた。

小ネタ2・暗黙のsubmitってあったんだね!?
業務中、こんな相談を受けました。
「テキストボックスにフォーカスしたままEnterを押すと、なぜか戻る動作が発動してしまうんだけど…」
と。

こんな感じのコードでした。

name=”return”っていかにも。どうやらこれがsubmitされて、画面遷移が行われているらしい。
しかしJS周りで特にそこをいじっている様子もなく、なんでだろうと首をひねっていたところ、
「あれ、このページ以外でも、テキストボックスでEnter押したら勝手にsubmitしたことになってないか?」
と気付きました。

まさか…と思い、W3C周りを調べてみたところ、なんとこんな項目が。
暗黙のsubmit。

hitting the “enter” key while a text field

まさにこれじゃないか。

ユーザがテキストボックスに入力して、その後すぐEnterを押してsubmitが実行されれば、
ユーザビリティとして便利やん!ってお話だったのですね…。

なお、複数のsubmitボタンがあった場合、一番はじめに出てくるsubmitが実行されるらしい。
だからreturnが送られていたのか…。

私が最初からバグだと決めつけてしまっていたので、「それって仕様じゃないのか?」「他でもそうなのか?」と多角的に考える気持ちを忘れていました。
それに、それなりに長いことフロントエンドに携わっていても、「こういう仕様だったの!?」と気付かされることが多いです。

日々勉強!って感じで、ほんとおもしろいですね、フロントエンド!
それでは、きょうはこのへんで。

JSONとJSONPの違いって?その2

継続は力なり!1ヶ月なにも書いてなかった!
こんにちは継続失敗した有村です。忙しかったの(言い訳)

前々回の ボタン作成で失敗したこと への記事にコメントありがとうございました!
超遅くなったのですが返信させていただきました!
ボタン周りはあれから1ヶ月、さらに色々と気付きがあったので、「失敗したことシリーズ」としてちょくちょく纏められたらいいな〜と思ってます!(どれだけ失敗する気)

さてさて、では今日のお題。前回の続き。
「JSONPを使えば、どうして他ドメインのJSONを使えるの?」という、「は?結論はよ」なところで止まっていました。書きます。

まず、JSONPについて。なんの略かというと…
JSON with padding
…marginとかそういう系?…ではなくて。ここでのpaddingは「不必要な挿入句」とか、要らないけど入れたわ、みたいなニュアンスらしい。

じゃあ何をpaddingしてるの?というと、JavaScript
じゃば…すくりぷと………?

一度、JavaScriptの特性(?)を。JavaScriptは、外部サイトのものでも実行できる。
「あ〜jQueryダウンロードしてサーバに上げてってやるのめんどくせ〜、Googleのとこから持ってくるようにしちゃお」
ってやりませんか?具体的にはこう。

Googleはどう考えても外部サイトですよね。そうじゃなかったらそれは中の人だ。

で、ここで衝撃の事実!(私的には)
JSONPは、JavaScriptの実行だった!!
えーーーーーー!!!!
JSONは、同一元生成ポリシー(XMLHttpRequest)に引っかかるから、別ドメインのデータを読めない。
ならば、別ドメインでも実行できるJavaScriptでデータを受け渡せば良いじゃないか!という発想。な、なるほど…!!

一連の流れとしては、雑にまとめるとこうらしい。

1.
コールバック関数を用意します。その中にJSONデータを利用した処理を書きます。実行時、引数にデータが入ってきます。

2. リクエストを投げます。
3. 「データを引数としてコールバックを実行する」というスクリプトとして返ってきます。1で用意したコールバックが呼び出されます。

4. コールバックが実行されます。

以上。

…ん?でもこれって、JavaScriptの実行を相手に委ねちゃってることにならないか?ということは、悪用される危険もあるのではないか…??
あ!だから適当にJSONP使ったら殴るって言われたんだ!
リスクや信頼性を考慮した上で実装しなさいよ、ってことだったんですね…。

というわけで、「JSONとJSONPの違いって?」の結びとしては…
JSONは同一ドメインでしか使えない。JavaScriptではない。
JSONPはJavaScript。
という感じでしょうか!

そういえば、先輩に「VPNってなんの略?」と聞かれて、「ばーちゃる… なんちゃらねっとわーく……」と答えてしまったので、
過去記事が全く身についてないことが分かりましたね!やった!!
それでは、きょうはこのへんで。

JSONとJSONPの違いって?その1

こんばんは、有村です。
気温の変化で、日々の服装に困る。

で、今日のテーマはJSONとJSONPの違いって?です!

Ajaxとか、フロントエンドならJSONを日常的に使いますね。
でも私、JSONPって、実は使ったことがなかったんです。使っても無意識のコピペくらい。
そういえば、「適当にJSONP使ったら殴る」って言われたこともありましたね…(遠い目)

なので、なんかよく分からないけどJSONPは危険なやつらしいってことと、他ドメインとのやりとり以外では使わないんだなってくらいしか理解していませんでした。
けど、なんでJSONPが危険なの?と改めて聞かれて答えられなかった&ついに使う機会に遭遇してしまったので、
少しづつ紐解いていこうと思いました。

まずは、JSONがなんの略か、から。
JavaScript Object Notation
notationは、特定の記号体系を持つ表記法のこと。なるほど。JavaScriptのオブジェクトの表記法、みたいな感じでしょうか。

MDNを見ると、

JavaScript の構文に基づいていますが、JavaScript とは異なります。

と書いてあります。あくまで別物ということですね。

で、先述のようにAjaxでJSONを読み込んで、それを基にDOMを操作したり(例えば「もっと見る」機能とか)すると思うんですが、
なぜJSONは別ドメインのものを使えないのでしょうか?
そこがクリアできれば、JSONPって要らないはずなのに。

理由は、ブラウザには同一生成元ポリシーというものがあって、自分(つまり表示中のページ)を生成したドメイン以外とは通信ができないようになっているから、らしい。
ええ…でもCSSとかJSとか、外部で読めるやん…と思ったのですが、ドンピシャで「XMLHttpRequest」が禁止されています。

Ajaxを使ってJSONデータ読み込むとき、XMLHttpRequestって使いますよね…つまり……
別ドメインのJSONを使えないのは、同一生成元ポリシーに引っかかるからなんだ!
なるほど…少しJSONちゃんのこと分かってきましたよ!

そしたら次に気になるのは、「JSONPを使えば、どうして他ドメインのJSONを使えるの?」ということなのですが…

まずはJSONをちょっと理解したところで、明日以降の続きに回したいと思います!力尽きた。

それでは、きょうはこのへんで。

function ◯◯ と var ◯◯ = function って何が違うの?

こんばんは、有村です!
連日更新してると、冒頭に何を書くかが浮かばない。

さてさて今日は、function ◯◯ と var ◯◯ = function って何が違うの?について書きます。

まず前提!
function hoge() → 関数宣言
var fuga = function() → 関数式
という名前がちゃんとあります!
実行時の書き方は、どちらも hoge()、fuga() 。定義の仕方が違うだけですね。
こんな感じ。

あれ?じゃあこの2つって、一体何が違うの。
実は駆け出しエンジニアだった頃、一度先輩に質問してみたことがありました。
しかし返ってきた答えは「ノリでええんちゃう^^^^」でした。
そこで「あ〜そうなんだ〜^^」と納得した私は関数式の存在自体を忘れていたのですが、長い時を経て、再び同じ問題と邂逅することになるのです…。

ある日先輩から、コードレビューにて「なんで関数宣言で書くの?」と聞かれた私は、「………理由はない。」と答えるのが精一杯でした。
そうですよね、それって何の理由にもなっていませんよね。というわけで、覚えました。

関数宣言 … 定義の中身も含めて巻き上げが起こる。
関数式 … 変数のみが巻き上げられ、定義の中身は巻き上げられない。

巻き上げって何、という方のための簡単な解説。
関数の途中などで「私はhogeって変数です!」と宣言すると、その宣言はスコープの先頭で宣言したことと同じになるということ。「先頭に巻き上げられる」ってことです。
ただ、「hogeって変数です!」という宣言と「値はほげです!」という定義は別物なので、例をあげるとすればこういうことになります。

ちなみに、宣言自体しないで呼び出すと、「Uncaught ReferenceError」になります。

で、話を戻すと、「関数宣言」は巻き上げの対象が「中身も含めて」実行されるのがポイントです。

関数宣言が呼び出しよりも後なのに、ちゃんと「ほげ」が出力されます。
逆に関数式で書いた場合は、関数式の定義よりも後で呼び出さないと「ほげ」が出ません。

じゃあどういうことだってばよって話なのですが、先輩はこう言いました。巻き上げって、副作用だわと。
そう言われるまで特に意識していませんでしたが、確かに「定義よりも前に動作する関数」って気持ち悪いですね。。
基本的にプログラムは上から実行されるものなのに、途中で宣言したものがさも最初から存在したかのように振る舞うわけですもんね。

…となると、関数宣言と関数式、どちらが実装する上でより適しているかを考えると、副作用が少ない関数式で書くほうがよいと思います。
宣言自体は巻き上げられているので、完全に副作用がないわけではないのですが…それでも関数宣言よりはマシですね!

ずーーーーーっと関数宣言で書いてきたJavaScriptの関数。すぐfunctionって書きたくなる衝動を抑えて、varから書きはじめる癖をつけてみます!
それでは、きょうはこのへんで。

既存関数をラップする

こんにちは。有村です。
ゲームは1日1時間、お勉強も1日1時間……………できれば理想ですね。

今日は手短に、「既存関数をラップする」について学んだことを書きます。

たとえばこのようなコードがあったとします。。

なんということはなく、hogeというclassを持つ要素をクリックしたらhoge();が実行され、hoge!ってアラートを出すだけですね。

それではこれはどうでしょうか。

追加実装で、hogeがさらにfugaというclassを持っていたら、hogeの前にfugaをアラートで出し、そうでなければ今まで通りという仕様に変わっています。

これは単純な例なのですが、実装って常に新規とは限らないですよね。
「既存の機能にあれを足したい」とか「この条件を変えたい」とか、そういうパターンのほうが多い気がします。
そうなったとき、上のコードで改良ポイントがあるとしたら、既存の関数を書き換えていることかなと思います。

というのも、hoge();は既に当初の実装でおそらく完成されており、テストも済んでいる内容です。
既存の関数を書き換えるということは、もちろんその中の処理が変わるということで、既存部分への影響考慮や関数全体の再テストが必要になります。。
なんなら、アラートにfugaを出すのは特殊なパターン(たとえばトップページだけ、とか)だけだったり、hoge();自体の処理は変えたくない!ということだってあると思います。

というわけで改良パターン。

alertの内容くらい引数で渡せや!というのは置いておいて…
どうでしょうか、既存の関数hogeは何も変わらず、代わりに「classにfugaを持っていたらこっち、持っていなかったらこっち」という案内役の関数と、fugaを持っていた場合の関数が足されました。
これであれば、既存関数hoge();自体は何も変わっていないので、影響の考慮やhoge();のテストは必要なくなりますね!

実装者は「今回の実装で既存の機能がぶっ壊れたんだけど;;」という展開を一番恐れる気がします…。
ので、できるだけ影響範囲が少なく、テストがしやすい実装を心がけたいものです!

それでは、今日はこのへんで。
ゲームしよう。

原則を知る ーDRYー

こんばんは、原田です。

さっき地元の知り合いから電話がきて、地元に帰りたくなりました。はい。

 

 

最近、上司に「どれが良い実装で、どれが悪い実装なのかが分からない」と相談しました。

すると、「原則を知るといい。」という助言を頂きました。

原則  …特別な場合は別として、一般に適用される根本的な法則。

確かに、原則を知ることは、いいコードが分かる導きになるかもしれないと思い、これからちょいちょい原則を書いていこうと思います!!!

 

ではでは、

今日の原則は〜・・・・

DRY

です。

乾燥という意味ではありません。(知らなかったのは私だけですかね?)

DRY(Don’t  Repeat Yourself)

重複を防ぐ考え方。

Single Source of truthとも言うそうです。

 

なぜ重複を防いだ方が良いのか?

重複が多い→変更時に変更箇所が増える→時間がかかる

情報量が多い→明確でない→不一致が生じる可能性がある

という点があるからだそうです。

 

ということで、今後はまとめることができたり、同じような実装が複数ある場合は、関数化したりしてDRYに努めようと思います。