jquery.ajaxに代わる、Fetch APIについて

Facebook にシェア
Pocket

最近のJavaScriptでは、jQueryに依存しない書き方が増えてきたようです。ただ、確かにセレクターなら、document.querySelectorAllメソッドを使えばいいだけなんですが、個人的にjQueryで便利なところは、ajaxだと思ってるんです。いちいち、XMLHttpRequestがどうちゃらこうちゃらとか書きたくないし、だいいち覚えられない。だから自分は、jQueryからはなかなか離れられないだろうし、離れたとしてもAjaxようの共通関数は実装することになるんだろうなぁ。と思っていたら、最近になってFetch APIなんてものを知りました。

最近のWeb技術界隈は追えていないと思ったらこんなものが。というわけで、調べて使ってみました。

HTML

PHP

サンプル:Document

やってることは、サーバーに数値と文字列をPOSTで渡すと、数値を2倍、文字列をSHA-256でハッシュ化した結果をJSON形式で返すというもの。例えば、数値を123、文字列をabcとすると下記のようになりました。

確かに数値は2倍になって、文字列はハッシュ化して返ってきました。ちょっとよく分からなかったのが、最初にResponseオブジェクトからどういう形式で値を取得するかという指定が必要なこと。これがPromiseオブジェクトで返ってくるので、いちいちthenを二回書かなきゃいけないという。response.json()で返ってくる値がPromiseオブジェクトじゃなくて、JSONオブジェクト(多重表現)になってるほうが直感的でわかりやすい気がするのだけど、多分、こうなってるメリットはあるんだろうと思う。このへんは多分、自分がPromiseについてよく分かってないから疑問に思ってるのだと思うので、もう少しこのへんも勉強していこうと思う。

ところで最初、fetchのbody部分を「body: new FormData(document.getElementById(‘frm’))」と指定しようと思ったのですが、それだといまいちメリットがないなと思ったら、JSONで渡せることを知ったのでそうしました。PHP側で『json_decode(file_get_contents(‘php://input’), true);』とすればいいそうです。初めて知りました。JSONのまま渡せるなら、便利ですね。これからはそうしようかな。

画面内に入ったり出たりした時の処理を行う「Intersection Observer」について

Facebook にシェア
Pocket

先日、超速! Webページ速度改善ガイド ── 使いやすさは「速さ」から始まる (WEB+DB PRESS plus)という本を読んで知ったのですが、最近のWebブラウザのJavaScriptには、「Intersection Observer」というAPIがあるらしく、このAPIを使うことで画面内に入ったか(もしくは画面外に出たか)どうかを判定できるそうです。

便利そうなので、試しに使ってみました。画面に四角い要素を100個並べて、画面に入ったり出たりすることで背景色が変わるサンプルです。試しに、今まで知ってはいたけど使ったことがないCSSアニメーションや、ES6から実装されたletやconstやアロー関数も使っています。

HTML

CSS

JavaScript

サンプル:Intesection Observeテスト

スクロールしたり画面サイズを変更したりすることで、四角い要素が画面内に入ると、背景色が1秒かけて青からオレンジに変わると思います(IE以外の最新ブラウザ対応)。

ただ、すばやくスクロールしているとたまにうまく動作しないことがあるみたいです。あまりアテにしすぎるのもよくないのかも(自分がよく分かってない可能性もおおいにあります)。

なお、IntersectionObserverの第2引数にはどの要素の交差を判定するか(なければブラウザのビューポート)のrootと、ルート回りの余白を指定できるrootMargin、それと可視性がどれぐらい入ってるか出ているかでコールバックを実行するthresholdというオプションがあるそうです。
参考:Intersection Observer API – Web API インターフェイス | MDN

超速!  Webページ速度改善ガイド ── 使いやすさは「速さ」から始まる (WEB+DB PRESS plus)
佐藤 歩 泉水 翔吾
技術評論社
売り上げランキング: 11,340

JavaScriptで日時の加減算を行う

Facebook にシェア
Pocket

またもや、改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用までから。

JavaScriptの日時処理は少し面倒だという印象があります。上で紹介した本を読んでも、ES2015でもそれは変わってないらしく、例えばフォーマットによる日時を付与した関数なんてものも用意されてないらしいです。

その点ではMoment.jsというライブラリ(参考:Moment.jsを使う – Qiita)がよさげではあるのですが、今回は素のJavaScriptを使った加減算について。

というのもやり方は簡単で、DateオブジェクトのgetXxxxxメソッドとsetXxxxxメソッドを使えばいいだけだそう。実は、本をよむまで、getとつくメソッドがあるのは知ってたけど、setとつくメソッドがあるのは知らなかった。

使い方としては以下。

見て分かるように、月をまたいでもちゃんと計算される(それにしてもなぜ、月だけ0始まりにしたのだろうか。最初間違えて、『new Date(2016,11,6,22,30);』として12月6日になって混乱した)。

これを応用したら、指定の日付の月末日を取得することができる。

ちなみに、setXxxxメソッドの戻り値は、Dateオブジェクトではなくて1970 年 1 月 1 日 00:00:00 からのミリ秒数。Dateオブジェクトだったらメソッドチェーンが利用できたので少し面倒。まあ、目的は変更後の日付を返すのではなく、自分自身の日付を変更するということだから仕方ないか。

まあ、やろうと思えば下記のようにできなくはない。

いや、これはメソッドチェーンとは言わないか。

というよりよくよく考えたら、Dateオブジェクトを新しく生成すればいいだけでした(調べて気づいた)。

なお、日付通しの計算については、getTimeメソッドを利用して数値化したうえで、1単位をミリ秒数で表した数で割らなきゃいけないそうです。

なんで標準でこれぐらいの計算が簡単にできるメソッドが用意されていないのだろうか……。ES2015では追加されるんじゃないかと期待していたのだけど……。

JavaScriptで、できるかぎり小数演算の誤差を少なくする方法

Facebook にシェア
Pocket

JavaScriptにかぎらず、プログラミングでの小数を含む演算では誤差が発生してしまうことがよくあります。例えば、『0.2+0.1』という単純な足し算すら、『0.30000000000000004』という結果になってしまいます(Chromeで確認した場合)。その対応方法が改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用までに書いてあったのでメモしておきます。

対応方法といっても単純なことで、ようは小数をいったん小数の長さ分の10の累乗を掛けて整数にしてから演算し、それから10の累乗分した数を割って正しい値を取得するというもの。最後の10の累乗で割るときに誤差が発生してしまうのではないかと思いそうですが、割られる方の数が整数であれば誤差は発生しないようです(例えば、『12.35/10』の結果は『1.2349999999999999』となるけど、『1235/1000』の結果は『1.235』となる)。

というわけで、小数の演算に対応した関数を書いてみました。

足し算、引き算、掛け算、割り算の4つの関数がありますが、上半分はすべて同じです。本来ならこの部分は共通化しておいたほうがいいでしょうね。エラー処理は余計だったかもしれません(この処理がなくても、どのみち例外エラーが発生するのだし、throwで返すのではなく、0やnullを返すとかでもいいかも)。

エラー処理はまず引数が数値かどうかチェックし、その後に指数表記かどうかを調べています。

実行した結果は下記のとおりです(『//=>』より右側が実行結果)。

ところで今回、小数って英語でなんていうんだけと思って調べて、英語でdecimalということを初めて知りました。decimalというと、10進数というイメージがあるのだけど、小数という意味もあったのかと。どっちの意味で使ってるか分かりづらいことってないのだろうか。

JavaScriptでローカル変数と同じ名前のグローバル変数を呼び出す方法(環境問わず)

Facebook にシェア
Pocket

今回も改訂新版JavaScript本格入門 ~モダンスタイルによる基礎から現場での応用までで知ったことから。

昔も似たようなタイトルで投稿したことあるのですが(JavaScriptでローカル変数と同じ名前のグローバル変数を呼び出す方法 | while(isプログラマ))、これはフロントエンド(ウェブブラウザ)限定の方法。グローバル変数はWindowオブジェクトに属しているから、windowオブジェクトのプロパティとして呼び出せばいいという話でした。今回は環境を問わず、例えばnode.jsでも通じる話。

その前に、JavaScriptでの関数の指定方法は4つあります。

1つ目は下記のようにfunction命令で定義する方法。

2つ目は下記のようにFunctionオブジェクトのコンストラクターを経由して定義する方法。

3つ目は下記のように関数リテラルで定義する方法

4つ目はES2015で追加されたアロー関数で定義する方法

どれも、『func(123)』とするとコンソールに『123』と出力されますが、実はそれぞれ微妙に違うそうです。例えば、function命令は静的な構造で定義より上で呼び出す記述があっても実行されるのに対し、関数リテラルやFunctionコンストラクターは実行時に評価されるので、定義より上で呼び出す記述があればエラーとなる等。

で、今回その違いで初めて知ったのが、Functionコンストラクターで定義した関数内の変数は、定義したスコープ内に同じ変数名があったとしてもグローバル変数を参照するということ。Functionコンストラクターなんて普段使わないから知りませんでした。

というわけで、以下サンプル。

2つ目の即時関数で、globalFuncやglobalAppleを用意して、それぞれFunctionコンストラクターで定義した即時関数からfunc関数とapple変数を取得しています。この結果は、同じスコープ内にappleという変数とfuncという関数があるにも関わらず、『global:10』となりました。つまり、グローバル変数を取得しているわけです。

まあ、現在のスコープ内に定義されている変数名と同じ名前のグローバル変数を取得することなんてそうそうないとは思いますが、Functionコンストラクターで定義した関数の中の変数はグローバル変数を参照するということは覚えておいたほうがいいかもしれません。「スコープ内で同じ名前の変数が存在してるのに、何でエラーになるんだろう?」となりかねません(もちろん、エラーになる理由はグローバル変数に同名の変数がないから)。

まあでも、最初に紹介した本にも書いてありましたが、Functionコンストラクターでの関数宣言は利用しないほうがいいと思います。分かりづらいです。文字列変数を利用して生成できるというメリットはあるかもしれませんが、その変数が外部から参照している値を利用していたらセキュリティ的に問題になる可能性があります。