エッジなWebエンジニアのためのブラウザー情報源
Chrome 38で<picture>要素のメディアクエリ対応と、JavaScriptのMap/Setオブジェクト&for-ofループ機能追加
<picture>要素ではレスポンシブUIに使えるメディアクエリが記述できるようになった。JavaScriptではコレクション用のMap/Setオブジェクトや、値を受け取って順次処理できるfor-ofループが追加された。
2014年10月14日にChrome 38が安定版として公開された(※バージョン37からは約2カ月ぶりのアップデート)。本稿では、Chrome 38で追加された機能について説明していく。
Chromeでは、仕様が安定しているものだけでなく、仕様策定中の機能も実装されることがある。Chrome 38で実装された全機能は、Chromium Dashboard(図1.1)で公開されている。
バージョンリストで「stable」と表示されているのが現在公開されている最新バージョンである。
Chromium Dashboardで[38 stable]をクリックすると、Chrome 38で実装されている機能を一覧で確認できる。また、[39 beta]をクリックすると、Chrome 39で実装予定の機能を確認できる。
緑色で表示されているものは、仕様が安定しており、ここから大きな変更がないもので、黄色、赤色と仕様の安定度が落ちていく。
本稿では、Chrome 38で実装された機能のうち、仕様が変更される可能性の少ない緑色のものに絞って解説していく。
<picture>要素の機能強化ポイント
<picture>要素は、機能としては<img>要素と同じく画像を表示するものだが、両者の違いともなる、Chrome 38の新機能は、レスポンシブUIに使えるメディアクエリを記述できるようになったことだ。
<picture>
<source media="(min-width: 650px)" srcset="large.png">
<source media="(min-width: 350px)" srcset="medium.png">
<img src="small.png" />
</picture>
|
子要素である<source>要素に画面の最小解像度(=min-width
プロパティ)が指定されている。
このように、<picture>要素の子要素として、<source>要素にメディアクエリ(=media
属性)を記述することで、解像度に合わせた画像を指定できるようになっている。また、<picture>要素に対応していないブラウザーのために<img>要素を記述している。
これをChrome 38で表示してみよう。
このように画面解像度に合わせて最適な画像が表示されていることが分かる。
これにより、スマホでPC用の画像をダウンロードして縮小表示するのではなく、スマホサイズに最適化された画像を表示できるようになる。もちろん、表示しない不要な画像がダウンロードされることはない。
ちなみに、<picture>要素に対応していないIE11で表示すると、<img>タグで記述されているsmall.pngが表示される(図1.3)。
<picture>要素には対応していないため、<img>要素で記述した画像が表示される。
JavaScriptの機能強化ポイント
Chrome 38では、策定中のECMAScript 6(=次期JavaScript言語仕様)で定義されている機能がいくつか実装されている。ここでは、新しく追加されたJavaScriptの機能について解説する。
Mapオブジェクト
Mapオブジェクトは、Key-Valueの組み合わせで値を管理するコレクションである。次のコードは、Mapオブジェクトの呼び出し例だ。
var m = new Map();
m.set(1, "aa");
m.set(2, "bb");
m.set("key", "value");
m.set(2, "cc");
console.log(m.get("key"));
m.forEach(function (item, key, mapObj) {
console.log("%s=%s", key, item);
});
|
setメソッドでキーと値の組み合わせで登録し、getメソッドやforEachメソッドで取得している。
このコードを[Console]パネルで実行してみよう。
setメソッドでキーと値の組み合わせでセットしている。また、2
という同じキーの値が2回セットされることで、aa
→cc
に上書きされている。
このようにsetメソッドでキーと値を指定してコレクションにセットしている。また、getメソッドやforEachメソッドでセットした値を取り出している。同じキーが指定されている「2」の値は「aa」から後で指定した「cc」に書き換えられている。
Setオブジェクト
Setオブジェクトは、一意の値を管理するコレクションである。
すでにセットされている値を追加しようとすると、その呼び出しは無視される(次のコード)。
var s = new Set();
s.add("test");
s.add("test"); // すでにセットされているため無視される
s.add(1);
s.add(2);
s.add(2); // すでにセットされているため無視される
console.log(s.size);
s.forEach(function (item) {
console.log("value=%s", item);
});
|
addメソッドで値が追加されるが、すでに追加されている値は無視される。
このコードを[Console]パネルで実行してみよう。
Addメソッドで値を追加して、結果を出力している。同じ値が追加されてもadd
呼び出しが無視されている。
addメソッドで「test」と「2」が2度ずつ追加されているが、無視されており、結果には1つだけ出力されていることが分かる。
for-ofループ
for-ofループは、配列や、上で解説したSetオブジェクトやMapオブジェクトなどのコレクションの値をループで処理できるようにする機能である。
これまでは、for-in
の記述で配列を処理することはできたが、このときに受け取れるのはインデックスであり、値を受け取ることはできなかった。実際のコードと動きを見てみよう。
var arr = ["a", "b", "c"];
console.log("for ... of");
for(var item of arr){
console.log(item);
}
console.log("for ... in");
for(var item in arr){
console.log(item);
}
|
作成した配列をfor-of
とfor-in
でそれぞれループしている。
このコードを[Console]パネルで実行してみよう。
for-ofでは配列の値が取得されているのに対して、for-inではインデックスが取得されている。
このようにfor-of
を使用すると、コレクションの値を直接取得して処理できるが、for-in
では配列のインデックスから実際の値を取得するというステップが必要になる。