Deep Insider の Tutor コーナー
>>  Deep Insider は本サイトからスピンオフした姉妹サイトです。よろしく! 
エッジなWebエンジニアのためのブラウザー情報源

エッジなWebエンジニアのためのブラウザー情報源

Chrome 38で<picture>要素のメディアクエリ対応と、JavaScriptのMap/Setオブジェクト&for-ofループ機能追加

2014年10月20日

<picture>要素ではレスポンシブUIに使えるメディアクエリが記述できるようになった。JavaScriptではコレクション用のMap/Setオブジェクトや、値を受け取って順次処理できるfor-ofループが追加された。

尾崎 義尚
  • このエントリーをはてなブックマークに追加

 2014年10月14日にChrome 38が安定版として公開された(バージョン37からは約2カ月ぶりのアップデート)。本稿では、Chrome 38で追加された機能について説明していく。

 Chromeでは、仕様が安定しているものだけでなく、仕様策定中の機能も実装されることがある。Chrome 38で実装された全機能は、Chromium Dashboard(図1.1)で公開されている。

図1.1 Chromium Dashboard

バージョンリストで「stable」と表示されているのが現在公開されている最新バージョンである。
Chromium Dashboardで[38 stable]をクリックすると、Chrome 38で実装されている機能を一覧で確認できる。また、[39 beta]をクリックすると、Chrome 39で実装予定の機能を確認できる。
緑色で表示されているものは、仕様が安定しており、ここから大きな変更がないもので、黄色赤色と仕様の安定度が落ちていく。

 本稿では、Chrome 38で実装された機能のうち、仕様が変更される可能性の少ない緑色のものに絞って解説していく。

<picture>要素の機能強化ポイント

 <picture>要素は、機能としては<img>要素と同じく画像を表示するものだが、両者の違いともなる、Chrome 38の新機能は、レスポンシブUIに使えるメディアクエリを記述できるようになったことだ。

HTML
<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で表示してみよう。

図1.2 <picture>要素の画像表示(上:(min-width: 650px)、中:(min-width: 350px)、下:<img>

画面解像度に合わせて最適な画像が表示される。

 このように画面解像度に合わせて最適な画像が表示されていることが分かる。

 これにより、スマホでPC用の画像をダウンロードして縮小表示するのではなく、スマホサイズに最適化された画像を表示できるようになる。もちろん、表示しない不要な画像がダウンロードされることはない。

 ちなみに、<picture>要素に対応していないIE11で表示すると、<img>タグで記述されているsmall.pngが表示される(図1.3)。

図1.3 IE11での<picture>要素の画像表示
図1.3 IE11での<picture>要素の画像表示

<picture>要素には対応していないため、<img>要素で記述した画像が表示される。

JavaScriptの機能強化ポイント

 Chrome 38では、策定中のECMAScript 6(=次期JavaScript言語仕様)で定義されている機能がいくつか実装されている。ここでは、新しく追加されたJavaScriptの機能について解説する。

Mapオブジェクト

 Mapオブジェクトは、Key-Valueの組み合わせで値を管理するコレクションである。次のコードは、Mapオブジェクトの呼び出し例だ。

JavaScript
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);
});
Mapオブジェクトの呼び出し例

setメソッドでキーと値の組み合わせで登録し、getメソッドやforEachメソッドで取得している。

 このコードを[Console]パネルで実行してみよう。

図2.1 Mapオブジェクトの実行結果
図2.1 Mapオブジェクトの実行結果

setメソッドでキーと値の組み合わせでセットしている。また、2という同じキーの値が2回セットされることで、aaccに上書きされている。

 このようにsetメソッドでキーと値を指定してコレクションにセットしている。また、getメソッドやforEachメソッドでセットした値を取り出している。同じキーが指定されている「2」の値は「aa」から後で指定した「cc」に書き換えられている。

Setオブジェクト

 Setオブジェクトは、一意の値を管理するコレクションである。

 すでにセットされている値を追加しようとすると、その呼び出しは無視される(次のコード)。

JavaScript
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);
});
Setオブジェクトの呼び出し例

addメソッドで値が追加されるが、すでに追加されている値は無視される。

 このコードを[Console]パネルで実行してみよう。

図2.2 Setオブジェクトの実行結果
図2.2 Setオブジェクトの実行結果

Addメソッドで値を追加して、結果を出力している。同じ値が追加されてもadd呼び出しが無視されている。

 addメソッドで「test」と「2」が2度ずつ追加されているが、無視されており、結果には1つだけ出力されていることが分かる。

for-ofループ

 for-ofループは、配列や、上で解説したSetオブジェクトやMapオブジェクトなどのコレクションの値をループで処理できるようにする機能である。

 これまでは、for-inの記述で配列を処理することはできたが、このときに受け取れるのはインデックスであり、値を受け取ることはできなかった。実際のコードと動きを見てみよう。

JavaScript
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ループの例

作成した配列をfor-offor-inでそれぞれループしている。

 このコードを[Console]パネルで実行してみよう。

図2.3 for-ofループとfor-inループの実行結果
図2.3 for-ofループとfor-inループの実行結果

for-ofでは配列の値が取得されているのに対して、for-inではインデックスが取得されている。

 このようにfor-ofを使用すると、コレクションの値を直接取得して処理できるが、for-inでは配列のインデックスから実際の値を取得するというステップが必要になる。

エッジなWebエンジニアのためのブラウザー情報源
1. 【現在、表示中】≫ Chrome 38で<picture>要素のメディアクエリ対応と、JavaScriptのMap/Setオブジェクト&for-ofループ機能追加

<picture>要素ではレスポンシブUIに使えるメディアクエリが記述できるようになった。JavaScriptではコレクション用のMap/Setオブジェクトや、値を受け取って順次処理できるfor-ofループが追加された。

エッジなWebエンジニアのためのブラウザー情報源
2. Chrome 39で追加されたGenerators機能とは

11月18日に公開されたChrome 39安定版の新機能を紹介。C#やRubyでおなじみのyieldキーワードが使えるようになった。

サイトからのお知らせ

Twitterでつぶやこう!