HTML5プロフェッショナル認定試験レベル2（Ver2.5）試験対策

# 概要
HTML5プロフェッショナル認定試験レベル2（Ver2.5）の試験対策記事です

勉強法ではなく，ここを覚えておくと良いという攻略法を主にまとめます
参考書などで一通り学習した後くらいの想定で書いてます

試験対策でなくても，JavaScriptに多少詳しくなれる記事だと思います

## 出題範囲
出題範囲は以下の通りです
この記事では一つ一つについて何を覚えていくと良いかまとめます
1. JavaScript
1. WebブラウザにおけるJavaScriptAPI
1. グラフィックス・アニメーション
1. マルチメディア
1. ストレージ
1. 通信
1. デバイスアクセス
1. パフォーマンスとオフライン
1. セキュリティモデル

https://html5exam.jp/outline/objectives_lv2.html

## JavaScript
範囲が広いのにJavaScriptの挙動がとてもくせつよなので，
対策が難しい箇所です

### use strict
下記のページを全部読むぐらい気持ちでいきましょう
出題数は多くないですが狙われる可能性は高いので注意が必要です

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Strict_mode

### 等価演算子
すごくよく出るので覚えておきましょう
等価「==」と厳密等価「===」の違いが大事です
プリミティブ型，オブジェクト，NaNに注目です

```javascript
console.log(1 == 1) // true
console.log(1 === 1) // true

// プリミティブ型同士を比較する場合
console.log('1' == 1) // true
console.log('1' === 1) // false

console.log(0 == false) // true
console.log(0 === false) // false

const pri_a = "文字列" // プリミティブ型の文字列
const pri_b = "文字列" // プリミティブ型の文字列
const obj_a = new String("文字列") // オブジェクトの文字列
const obj_b = new String("文字列") // オブジェクトの文字列

// プリミティブ型同士を比較する場合
console.log(pri_a == pri_b) // true
console.log(pri_a === pri_b) // true

// プリミティブ型とオブジェクトを比較する場合
console.log(pri_a == obj_a) // true
console.log(pri_a === obj_a) // false

// オブジェクト同士を比較する場合
console.log(obj_a == obj_b) // false
console.log(obj_a === obj_b) // false

const bool_a = new Boolean(false)
const bool_b = new Boolean(false)

console.log(bool_a == bool_b) // false
console.log(bool_a === bool_b) // false

console.log(bool_a == false) // ture
console.log(bool_a === false) // false

// NULL と undefined の比較
console.log(null == undefined) // true
console.log(null === undefined) // false

// NaN の比較
// NaN を比較した段階で相手がなんであろうと false
const nan_a = NaN
const nan_b = NaN

console.log(nan_a == NaN) // false
console.log(nan_a === NaN) // false
```

### let
`let` のスコープはブロックスコープです
ブロックスコープですので，
スコープが変われば同じ名前で変数をつくれます
参考に載せてる下記のページを参考ですが，
少しだけ確認するとこんな感じです

```javascript
let let_hensu = "外側のスコープ";
const getLetHensu = () => {
    let_hensu = "関数内のスコープ" // 外側のlet_hensuと同じ子
}
getLetHensu()
console.log(let_hensu) // 「関数内のスコープ」が表示される
```

```javascript
let let_hensu = "外側のスコープ";
const getLetHensu = () => {
    // ここを変更
    let let_hensu = "関数内のスコープ" // 外側のlet_hensuと違う子
}
getLetHensu()
console.log(let_hensu) // 「外側のスコープ」が表示される
```

https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/let#%E3%82%B9%E3%82%B3%E3%83%BC%E3%83%97%E3%81%AE%E3%83%AB%E3%83%BC%E3%83%AB

https://qiita.com/jonakp/items/c943c8d457871fa6ceb6


### const
定数を宣言するときに `const` を使いますが，
「定数だから再代入できない・変更はできない」
そう思っていると足元をすくわれます

> const 宣言はブロックスコープのローカル変数（定数）を宣言します。
> 定数の値は代入演算子を使用して再代入することができませんが、
> 定数がオブジェクトであった場合、
> そのプロパティを追加したり、更新したり、削除したりすることができます。

何を言っているかというとこうです

```JavaScript
const pri = "プリミティブな定数"
pri = "再代入" // 再代入できないのでエラーが出る

const obj = {"キー1": "値1", "キー2": "値2"}

obj["キー1"] = "再代入" // オブジェクトなのでプロパティは変更できる
console.log(obj) // Object { キー1: "再代入", キー2: "値2" }

// オブジェクト自体の再代入はエラーがでる
// 元々オブジェクトなのに配列を入れたからエラーが出るというわけではないので注意
obj = [1, 2, 3] 
```


https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Statements/const#%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%A8%E9%85%8D%E5%88%97%E3%81%AE%E5%AE%9A%E6%95%B0

### this
とても癖がつよく難敵です
確実に抑えておきたいです
試験で出題されなかったら逆にラッキーです

関数式かアロー関数かで`this`の値が変わります

#### 関数式
`this` には呼び出し元が入ります
呼び出し元は `.` の左側の子のことです
`xx.fun()` の場合，`this` には `xx` が入ります

```javascript
const obj_fun = {
    fun: function() {
        console.log(this)
    }
}
obj_fun.fun() // thisには呼び出し元のobj_fun が入る
```

#### アロー関数
`this` には呼び出し元**ではなく**，
定義した時点のオブジェクトが入ります

```javascript
const obj_al = {
    fun: () => {
        console.log(this)
    }
}
obj_al.fun() // thisにはWindowオブジェクトが入る
```

詳細にみていくとこんな感じです

```javascript
console.log(this)
this.name = "Windowのname"

// この時点の this は Window オブジェクト
console.log(this.name) // Windowのname

let obj = {
    name: "objのname",
    onamae: "objのonamae",
    name_func: function() {
    // 関数式
    // メソッド呼び出し
    // 呼び出し元は obj
        console.log(`name_func: ${this.name}`) // objのname
        console.log(`name_func: ${this.onamae}`) // objのonamae
    },
    name_arrow: () => {
    // アロー関数
    // グローバルオブジェクト
        console.log(`name_arrow: ${this.name}`) // Windowのname
        console.log(`name_arrow: ${this.onamae}`) // undefined
    },
    name_func_arrow() {
        console.log(`name_func_arrow: ${this.name}`) // objのname
        console.log(`name_func_arrow: ${this.onamae}`) // objのonamae

        const fun = function() {
        // 関数式
            console.log(`fun: ${this.name}`) // Windowのname
            console.log(`fun: ${this.onamae}`) // undefined
        }
        // 関数呼び出し
        // window.fun() と同じ意味になる（独自のバインドを持つ）
        fun()

        const arr = () => {
            // アロー関数
            // 宣言時点の this.name は objのname
            console.log(`arr: ${this.name}`) // objのname
            console.log(`arr: ${this.onamae}`) // objのonamae
        }
        // 関数呼び出し
        // 独自のバインドを持たないので，
        // この時点で window にバンドされず
        // obj にバインドされる
        arr()
    }
}
obj.name_func()
obj.name_arrow()
obj.name_func_arrow()

```

また，`addEventListener` 内での `this` も押さえておきたいので，
下記のありがたいページを参考しましょう

https://zenn.dev/u1e2k/articles/ec4e4f37287980


### Promise, async/await
非同期処理についてです
確実に抑えておきたいです
試験で出題されなかったら逆にラッキーです

https://ja.javascript.info/async

加えて絶対に `Promise.all` まで抑えておきましょう
特にいかが大切です
- 処理の順番
- 全部成功した時の挙動
- 途中で失敗したときの挙動

こちらがとてもとてもまとまっているので参考になります

https://ja.javascript.info/promise-api#ref-1091



## WebブラウザにおけるJavaScriptAPI

### SelectorsAPI
覚えておきたいのは，
`querySelectorAll` で取得できるのは**静的**なリスト(NodeList)で，
`getElementsBy` 系で取得できるのは**動的**なリスト（HTMLCollection)です

**静的**と**動的**が何かというと，
静的は参照した時点の情報なので，変更されようが変わりません
動的は変更されたら即時反映されます
詳しくはこちらを

https://qiita.com/ari-chel/items/b06c68aec8849d0409dd#%E5%8F%96%E5%BE%97%E3%81%A7%E3%81%8D%E3%82%8B%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%81%AE%E9%81%95%E3%81%84%E3%81%A7%E8%80%83%E3%81%88%E3%82%8B

## グラフィックス・アニメーション
### arc
円弧を作成します
作成するだけなので，描画の関数が必要です
`stroke()` で円弧を描画したり，
`fill()` で塗りつぶしの円を描画したりです

```javascript
arc(x, y, radius, startAngle, endAngle, counterclockwise)
```

引数についてはこんな感じです
| 引数 | 説明 |
|:--|:--|
|x|**中心**のx座標|
|y|**中心**のy座標|
|radius|半径|
|startAngle|始点の角度|
|endAngle|終点の角度|
|counterclockwise|falseなら時計回り，trueなら反時計回り|

では具体的に見てみましょう
以下の設定で円弧を描きます
- 中心座標が(50, 50)
- 半径が 40
- 0 ~ 1/2 * π 
- 時計回り

```html
<canvas id="arc"></canvas>
```

```javascript
const arcCanvas = document.getElementById("arc")
const ctx = arcCanvas.getContext("2d")

ctx.beginPath()
ctx.strokeStyle = "yellow"
ctx.arc(50, 50, 40, 0, 1/2 * Math.PI, false)
ctx.stroke()
```

![arc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/294646/128dc701-b694-fce0-f976-2c576b5f1166.png)

### SVG画像の埋め込み
SVG画像を埋め込む方法がいくつかありますが，
余裕で狙われますので抑えておきましょう

https://www.freecodecamp.org/japanese/news/use-svg-images-in-css-html/


## マルチメディア
ここについては例題で問われているところを抑えておきましょう
そのままは出ませんが，ここで得た知識が活きます

https://html5exam.jp/measures/lv2_4.html

加え以下も抑えておくと心強いです

### 変形
よくあるのが `video` タグで再生している動画を
`canvas` に描画する問題です
その時，問題のもう一押しで左右反転させたりします
ということで変形する関数と内容を覚えておきたいです

canvas.scale()
https://developer.mozilla.org/ja/docs/Web/CSS/transform-function/scale

canvas.setTransform()
行列の演算が出ますが実際の試験でも出題されるので，
試験までにはなんとか覚えましょう
https://www.htmq.com/canvas/setTransform.shtml

## ストレージ
### WebStorageとIndexedDB
WebStorageとIndexedDBの違いと仕様についてよく出ます
特にWebStroageは全部文字列で保存されるということは覚えておかないと痛い目を見ます
逆に他のストレージは文字列の他にバイナリデータなども保存できる点も大事です
こちらの記事がとてもまとまっているので抑えておきましょう
https://wellknowledge.org/cache-session-cookie-webstorage/

### FileAPI
ほぼほぼ一問は出題されるので抑えましょう
https://qiita.com/wada1355/items/8028d87d8d2bc6c00e69

もちろん例題も抑えておきましょう
https://html5exam.jp/measures/lv2_5.html

## 通信
### WebSocket
抑えおきたいのは以下です
- サーバーサイドのアーキテクチャも変更が必要になる
- 古いブラウザ（レガシー）はサポートしていない場合がある

WebSocketとはについてはこちらの記事が参考になります
https://zenn.dev/nameless_sn/articles/websocket_tutorial

### XMLHttpRequest
確実に出ると思って良いです
下記のページで覚えつつ例題は解くようにしましょう

https://ja.javascript.info/xmlhttprequest

https://html5exam.jp/measures/lv2_6.html

### Server-Sent Events
「Server-Sent EventsのMIME-Type」これは抑えおきましょう

https://developer.mozilla.org/ja/docs/Web/API/Server-sent_events/Using_server-sent_events#%E3%82%B5%E3%83%BC%E3%83%90%E3%81%8B%E3%82%89%E3%81%AE%E3%82%A4%E3%83%99%E3%83%B3%E3%83%88%E3%81%AE%E9%80%81%E4%BF%A1

## デバイスアクセス
### Geolocation API
位置情報を取得するAPIです
まず，`navigator.geolocation`でアクセスします
`navigator`なんですね

取得できる情報はこちらを参照です

https://blog.codecamp.jp/javascript-geolocation

### DeviceOrientation Event
おそらくですが毎回1問は出る気がします
向きとどの角度までの範囲なのかが大事です

| 向き | 説明|角度 |
|:--|:--|:--|
|alpha|Z軸回り|0° <= Θ < 360°|
|beta|x軸回り|-180° <= Θ < 180°|
|gamma|y軸回り|-90° <= Θ < 90°|


https://triple-underscore.github.io/deviceorientation-ja.html#device-orientation-model

## パフォーマンスとオフライン

### Web Workers
抑えておきたいのは以下です
- Worker で Worker を作ることができる
- DOMツリーを直接操作することはできない
- やりとりは`postMessage()`で行う（文字列でやりとり）

あとは例題もやっておきたいです

https://html5exam.jp/measures/lv2_8.html

### High Resolution Time
取得する時は `Perfomance.now()`
取得できる秒数は**ミリ秒**まで
精度は**マイクロ秒**


### オフラインアプリケーションAPI
ブラウザーのオンライン状態を確認するプロパティを覚えておきましょう
`navigator`を経由して取得します（ここが大事）

```javascript
navigator.onLine // オンラインだと ture
```

https://developer.mozilla.org/ja/docs/Web/API/Navigator/onLine

##  セキュリティモデル
### クロスオリジン制約とCORS
特に大事なのは**Access-Control-Allow-Origin** ヘッダーです
この子がいればとりあえず通信ができるそうです

その他は例題をやっておくと良いです

https://html5exam.jp/measures/lv2_9.html

### セキュリティモデルとSSLの関係
SSL/TLS でない利用できない API が特に大事です
Service Worker と geolocation が特に大事です

## 体験談
ここからは体験談です
1 回目は 67 点で不合格
公式の教科書（リファレンス）と例題を 2 週くらいして挑みましたが，
余裕で落ちました...
1 発で合格できなかったのが悲しいです...

2 回目は 95 点で合格でした
1 回目から 2 回目受けるまでの期間は 2 週間でした
2 週間でやったことは，
1 回目で自信なかったところを覚えていた範囲で勉強したのと，
Ver2.0(一つ古いバージョン）の問題集を買って解きました


1 回目落ちた原因としては以下が挙げられます
- JavaScript の問題が想定より難しかった
    - `this` の対策が甘かった
    - 普段 `Python` に慣れているのでその感覚で解いてしまった
- `navigator` を `location` と勘違いした
- セキュリティからの出題が 0 点だった

といった感じです
特にJavaScriptに足元をすくわれたのが大きかったですね
JavaScriptの奥の深さというかじゃじゃ馬にてんてこまいでしたね

2 回目受かった原因としては以下が挙げられます
- JavaScriptで 1 回目できなかったところに加え，問題集で知識を深められた
- セキュリティについて問題集で対策できた
- 問題集で全体的に足りないところを補えた

といった感じです
問題集は現時点(2024/08/04)では前のバージョン(Ver2.0)しか出てないですが，
良い問題集なので最初から買っておけばよかったなと思いました
あとは，「ES6（ECMAScript2015）以降に追加された機能および表記法」は
容赦なく出てくるので教科書や 1 回目で痛い目をみたところを重点的にやりました
正直JavaScirptからは 1 回目の問題は 1 問も出ませんでしたが，
なんとか気合でいけました
これをご覧になっている方には，ぜひこの記事で書いてあることを抑えていただくと私のような悲劇を味わはずに済むと思いますb

みなさんの力になれればと思いますb