見出し画像

HTML5 レベル2 過去問 勉強記録

資格取得のためここで記録を残す





上記のページのコードを使ったJavaScriptの例

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JavaScriptの基本</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            margin: 20px;
        }
        code {
            background-color: #f4f4f4 ;
            padding: 2px 4px;
            border-radius: 4px;
        }
        pre {
            background-color: #f4f4f4 ;
            padding: 10px;
            border-radius: 4px;
            overflow-x: auto;
        }
    </style>
</head>
<body>
    <h1>JavaScriptの基本</h1>
    <p>以下はJavaScriptの基本的な構文とその説明です。</p>
    <pre>
<code>
// 数字と演算子
3; // = 3
1.5; // = 1.5
1 + 1; // = 2
0.1 + 0.2; // = 0.30000000000000004

// 文字列
'abc';
"Hello, world";

// 論理演算
true && false; // = false
true || false; // = true

// 比較演算子
1 === 1; // = true
1 !== 1; // = false

// 配列
var myArray = ["Hello", 45, true];
myArray[1]; // = 45

// オブジェクト
var myObj = {key1: "Hello", key2: "World"};
myObj.key1; // = "Hello"
myObj["key2"]; // = "World"

// 関数
function myFunction(thing) {
    return thing.toUpperCase();
}
myFunction("foo"); // = "FOO"

// ループと条件文
for (var i = 0; i < 5; i++) {
    console.log(i);
}

if (count == 3) {
    console.log("Count is 3");
} else {
    console.log("Count is not 3");
}
    </code>
    </pre>
    <h2>実行結果</h2>
    <button onclick="runCode()">コードを実行</button>
    <script>
        function runCode() {
            // コンソールに出力
            console.log("=== 数字と演算子 ===");
            console.log(3); // = 3
            console.log(1.5); // = 1.5
            console.log(1 + 1); // = 2
            console.log(0.1 + 0.2); // = 0.30000000000000004

            console.log("=== 文字列 ===");
            console.log('abc');
            console.log("Hello, world");

            console.log("=== 論理演算 ===");
            console.log(true && false); // = false
            console.log(true || false); // = true

            console.log("=== 比較演算子 ===");
            console.log(1 === 1); // = true
            console.log(1 !== 1); // = false

            console.log("=== 配列 ===");
            var myArray = ["Hello", 45, true];
            console.log(myArray[1]); // = 45

            console.log("=== オブジェクト ===");
            var myObj = {key1: "Hello", key2: "World"};
            console.log(myObj.key1); // = "Hello"
            console.log(myObj["key2"]); // = "World"

            console.log("=== 関数 ===");
            function myFunction(thing) {
                return thing.toUpperCase();
            }
            console.log(myFunction("foo")); // = "FOO"

            console.log("=== ループと条件文 ===");
            for (var i = 0; i < 5; i++) {
                console.log(i);
            }

            var count = 2;
            if (count == 3) {
                console.log("Count is 3");
            } else {
                console.log("Count is not 3");
            }
        }
    </script>
</body>
</html>

上記のページのコードを使ったjQueryの例


  1. HTML構造:

    • <head>セクションでjQueryライブラリをCDNからインポート

    • <style>セクションで基本的なスタイルを定義

    • <body>セクションには、見出し、ボタン、段落、そしていくつかのdiv要素が含まれる

  2. jQueryコード:

    • セレクター: $(window), $('p'), $('#table1'), $('.square'), $('p.square')を使って要素を選択

    • イベントとエフェクト:

      • ドキュメントが読み込まれた後に実行されるコードを$(document).readyで定義

      • ボタンに対して、クリック、ダブルクリック、ホバーなどのイベントを設定

      • $('.table')を使って、テーブル要素を非表示にしたり、フェードイン、アニメーションを設定

      • $('div').addClass('taming-slim-20')で全てのdiv要素にクラスを追加

      • $('p').eachで全ての段落の高さを取得し、コンソールに出力

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>jQuery Example Page</title>
    <script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
    <style>
        .square {
            width: 100px;
            height: 100px;
            background-color: red;
            margin: 10px;
        }
        .hidden {
            display: none;
        }
    </style>
</head>
<body>
    <h1>jQuery Example Page</h1>
    <button id="btn">Click Me</button>
    <p>This is a paragraph.</p>
    <p class="square">This is a square paragraph.</p>
    <div id="table1" class="table">Table 1 Content</div>
    <div class="table">Table 2 Content</div>

    <script>
        // 1. Selectors
        var page = $(window);
        var paragraph = $('p');
        var table1 = $('#table1');
        var squares = $('.square');
        var square_p = $('p.square');

        // 2. Events and Effects
        $(document).ready(function() {
            console.log('Document is ready');

            $('#btn').click(function() {
                alert('Button clicked!');
            });

            $('#btn').dblclick(function() {
                alert('Button double clicked!');
            });

            $('#btn').hover(function() {
                console.log('Button hovered!');
            });

            $('#btn').on({
                blur: function() {
                    console.log('Button lost focus');
                },
                mouseenter: function() {
                    console.log('Mouse entered button');
                },
                mouseleave: function() {
                    console.log('Mouse left button');
                }
            });

            $('.table').hide(1000, function() {
                console.log('Table hidden');
            });

            var tables = $('.table');
            tables.fadeIn(2000, function() {
                console.log('Table faded in');
            });

            tables.animate({marginTop:"+=50px", height: "100px"}, 500, function() {
                console.log('Table animated');
            });

            $('div').addClass('taming-slim-20');

            $('p').each(function() {
                console.log('Paragraph height:', $(this).height());
            });
        });
    </script>
</body>
</html>











JavaScript

MIMEタイプはtext/javascript, application/javascript

scriptタグのtype属性に、text/javascript を指定する

1)
<script type="text/javascript">
   ここに記述
</script>


2) typeは省略可能
<script>
</script>



3) 外部ファイル読み込み
<script scr="sample.js"></script>

JavaScriptの標準化の団体はECMA International

W3CはHTML, CSS, DOMの標準化を行う

JavaScriptの識別子

アルファベット、アンダーバー、$で始まる
2文字目以降は、数字も使用可能
・予約語は使用できない
 

予約語

break, case, catch, class, const, continue, debugger, default, delete, do, else, export, extends など


アルファベットで始まる識別子:

username
totalAmount
dataValue





アンダーバー(_)で始まる識別子:

_count
_myValue
_tempVar





ドル記号($)で始まる識別子:

$id
$price
$element



変数の値

以下は、100と表示される
JavaScriptは変数のデータ型が柔軟(動的型付け)

var msg = "hello";
msg = 100;
console.log(msg);

JavaScriptのデータ型

データ型は、プリミティブ型とオブジェクト型に分けることが出来る

プリミティブ型
 文字列、数値、真偽値、null、undefined、シンボル

オブジェクト型
 配列

それぞれ変数への値の格納が異なる

プリミティブ型

文字列: 'Hello, World!', "JavaScript"

数値: 42, 3.14

真偽値: true, false

null: null (何もないことを意味する特別な値)

undefined: undefined (値が未定義であることを示す)

シンボル: Symbol('id') (一意かつ変更不可能な値)


// 文字列
let str = "Hello, World!";
console.log(str);

// 数値
let num = 42;
console.log(num);

// 真偽値
let bool = true;
console.log();

// null
let empty = null;
console.log(empty);

// undefined
let notDefined;
console.log(notDefined);

// シンボル
let sym = Symbol("unique");
console.log(sym);

// 配列
let arr = [1, 2, 3, "four", true];
console.log(arr);


オブジェクト型

配列: [1, 2, 3], ["apple", "banana", "cherry"]

オブジェクト: { name: "Alice", age: 25 }

関数: function sayHello() { console.log("Hello!"); }

Date: new Date()

RegExp: /abc/

Map: new Map()

Set: new Set()

WeakMap: new WeakMap()

WeakSet: new WeakSet()



// 配列
let numbers = [1, 2, 3];
let fruits = ["apple", "banana", "cherry"];
console.log(numbers);
console.log(fruits);

console.log(numbers[2]);
console.log(fruits[0]);



// オブジェクト
let person = {
    name: "Alice",
    age: 25
};
console.log(person);
console.log(person.name);
console.log(person.age);

person.bark = "bark";
console.log(person);
console.log(person.bark);




// 関数
function sayHello() {
    console.log("Hello!");
}
sayHello();


// Date
let currentDate = new Date();
console.log(currentDate);


// RegExp
let regex = /abc/;
console.log(regex);


// Map
let map = new Map();
map.set("key1", "value1");
map.set("key2", "value2");
console.log(map);


// Set
let set = new Set();
set.add(1);
set.add(2);
set.add(3);
console.log(set);


// WeakMap
let weakMap = new WeakMap();
let obj1 = {};
let obj2 = {};
weakMap.set(obj1, "value1");
weakMap.set(obj2, "value2");
console.log(weakMap.get(obj1)); 
console.log(weakMap.get(obj2)); 




// WeakSet
let weakSet = new WeakSet();
let obj3 = {};
let obj4 = {};
weakSet.add(obj3);
weakSet.add(obj4);
console.log(weakSet.has(obj3));
console.log(weakSet.has(obj4));


ラッパーオブジェクト

プリミティブ型の値を操作する機能を付与するためのオブジェクト

主なラッパーオブジェクト:
  Number
  String
  Boolean

Numberオブジェクトのプロパティ

MAX_VALUE
MIN_VALUE


Stringオブジェクトのプロパティとメソッド

length
charAt
indexOf
concat
split
substring
match
replace


var cat = "抜山ラム,ネコ,1";
console.log(cat.length); // 9

var catInfo = cat.split(",");
console.log(catInfo.length); // 3


Dateオブジェクトのメソッド

getFullYear()
getMonth()
getDate()
getDay()
getHours()
getMinutes()
getSeconds()

setFullYear()
setMonth()
setDate()
setHours()
setMinutes()
setSeconds()
toLocaleString()









var now = new Date();

console.log(now.getMonth() + "月");
console.log(now.getDate() + "日");
console.log(now.getDay() + "曜日");


4120曜日


RegExpオブジェクト

主なメソッド

test()
exec()

Mathオブジェクト

主なプロパティとメソッド

PI
E
ceil()
floor()
round()


JavaScript組み込みオブジェクト = グローバルオブジェクト

・予め提供されているオブジェクトだり、全てのオブジェクトの最上位
・new演算子で生成できない
・windowsオブジェクトは、ブラウザにおけるグローバルオブジェクト


主な組み込みオブジェクト

Object
 全てのオブジェクトの既定のプロトタイプ
Date
 日付の操作を行うためのオブジェクト
JSON
 JSON形式のデータを扱うためのオブジェクト
Array
 配列を扱うためのオブジェクト
Math
 算術計算を行うためのオブジェクト
Error
 エラー情報を扱うためのオブジェクト
RegExp
 正規表現オブジェクト
ラッパーオブジェクト
 プリミティブ型の値を操作する




プリミティブ型とラッパーオブジェクトの違い


これらの式には実用上の違いはほとんどない
var str = String("Hello"); と var str2 = "Hello";
var num = Number(1); と var num2 = 1;

・しかし、既に型が明らかな場合(例えば文字列や数値を直接代入する場合など)はリテラルを使用する方が一般的

・String や Number 関数は、異なる型からの変換が必要な場面で主に使われる

例) ユーザー入力が文字列として受け取られるが、それを数値として扱いたい場合


var str = String("Hello");
var str2 = "Hello"; // リテラル


var num = Number(1);
var num2 = 1; // リテラル


Arrayオブジェクトのメソッド


length
 配列の要素数
pop()
 最後の要素を削除
push()
 最後の要素の後に、要素を追加
concat()
 配列に他の配列や値を連結する
sort()
 配列の並び替え
forEach()
 要素分、処理を繰り返す
var num = [1,2,3,4,5,6,7,8,9,10];

num.forEach(function (value) {
   if (value % 2 == 0) {
       console.log(value + "は偶数です");
   } 
});


2は偶数です
4は偶数です
6は偶数です
8は偶数です
10は偶数です
var array = ["banana", "apple", "orange"];
var array2 = new Array("banana", "apple", "orange");
var array3 = ["banana", "apple", ["orange", "grapefruit"]];

console.log(array[0]);
console.log(array2[0]);
console.log(array3[2][0]);



banana
banana
orange


var array = ["banana", "apple", "orange"];
array[3] = 100; // 4番目の要素として代入される

console.log(array.length); // 4


var array = [];
array[3] = "banana";

console.log(array[0]); // undefined
console.log(array.length); // 4


var fruits = ["banana", "apple", "orange"];
fruits.pop();
console.log(fruits.length); // 2

fruits.push("apricot");
console.log(fruits.length); // 3

fruits.concat(["peach", "cherry"]);
console.log(fruits.length); // 3


JSONオブジェクト

JSONデータを扱うための組み込みオブジェクト

JSONの特徴
・複数項目を文字列で表現できる
・XMLに比べてデータ構造が単純で軽量である
・JavaScriptで標準的にサポートされている

JSONオブジェクトのメソッド

parse() 
 JSON -> JavaScriptオブジェクト に変換する

stringify()
 JavaScriptオブジェクト -> JSON に変換する
// JSON.parse() メソッドは、JSON文字列をJavaScriptのオブジェクトに変換
let jsonString = '{"name": "Alice", "age": 25, "isStudent": false}';
let jsonObject = JSON.parse(jsonString);

console.log(jsonObject); // { name: 'Alice', age: 25, isStudent: false }
console.log(jsonObject.name); // Alice
console.log(jsonObject.age); // 25
console.log(jsonObject.isStudent); // false




let response = '{"status": "success", "data": {"id": 1, "name": "Alice"}}';
let parsedResponse = JSON.parse(response);

console.log(parsedResponse.status); // success
console.log(parsedResponse.data.name); // Alice





// JSON.stringify() メソッドは、JavaScriptのオブジェクトをJSON文字列に変換
let jsObject = {
    name: "Alice",
    age: 25,
    isStudent: false
};
let jsonString = JSON.stringify(jsObject);

console.log(jsonString); // '{"name":"Alice","age":25,"isStudent":false}'





let user = {
    id: 1,
    name: "Bob",
    roles: ["admin", "editor"]
};
let userString = JSON.stringify(user);

console.log(userString); // '{"id":1,"name":"Bob","roles":["admin","editor"]}'





等価演算子とラッパーオブジェクトを使った場合

・それぞれ異なるメモリ上のアドレスでオブジェクトが生成される
だからnum1とnum2, str1とstr2は異なるオブジェクト。よってfalseとなる

・オブジェクトをプリミティブ値と比較する際、オブジェクトはプリミティブ型に自動的に変換される
なので、   object == 100 となる場合は、trueとなる

var num1 = new Number(100); // ラッパーオブジェクトを生成
var num2 = new Number(100); // ラッパーオブジェクトを生成

var str1 = new String("100"); // ラッパーオブジェクトを生成
var str2 = new String("100"); // ラッパーオブジェクトを生成



console.log(num1 == num2); // false
console.log(num1 == str1); // false
console.log(str1 == str2); // false
console.log(num1 == 100); // true
console.log(str1 == 100); // true


プリミティブ型の場合

var num1 = 100;
var num2 = 100;

var str1 = "100";
var str2 = "100";


console.log(num1 == num2); // true
console.log(num1 == str1); // true
console.log(str1 == str2); // true
console.log(num1 == 100); // true
console.log(str1 == 100); // true




数値でないプロパティ NaN (Not a Number) 

NaNになる場合、
・0を0で除算する
・InfinityをInfinityで除算する

var num1 = NaN;
var num2 = NaN;

console.log(0 / 0);
console.log(num1 == num1);
console.log(num1 == num2);

console.log(isNaN(0 / 0));


結果がInfinityになる式

Infinityは全ての値より大きい値を表す

console.log(1 / 0);
console.log(Infinity + 1);


console.log(1 / 0);
console.log(Infinity / 1);
console.log(-1 / 0);
console.log(Infinity / Infinity);
console.log(Infinity + 1);
console.log(Infinity + Infinity);
console.log(Infinity - 1);
console.log(Infinity - Infinity);
console.log(Infinity * 3);
console.log(Infinity * -3);
console.log(Infinity * Infinity);


Infinity
Infinity
-Infinity
NaN
Infinity
Infinity
Infinity
NaN
Infinity
-Infinity
Infinity


undefined 値が定義されてない

undefinedになる場合
・値を代入していない変数を使用しようとした場合
・定義されていないプロパティにアクセスした場合
・関数に戻り値が指定されていない場合





演算子

算術演算子

+
-
*
/
**
%
++
--


代入演算子

=
+=
-=
*=
/=


等価演算子

==
===
!=
!==


関係演算子

>
<
>=
<=
in
instanceof


論理演算子

&&
||
!


ビット演算子

<<
>>


間違えやすい演算子

// べき乗演算子(**)
let power = 2 ** 3; // 2の3乗、結果は8
console.log(power); // 8



// 剰余演算子(%)
let remainder = 10 % 3; // 10を3で割った余り、結果は1
console.log(remainder); // 1




// インクリメント演算子(++)
let increment = 5;
increment++;
console.log(increment); // 6




// デクリメント演算子(--)
let decrement = 5;
decrement--;
console.log(decrement); // 4




// 乗算代入演算子(*=)
let multiplyAssign = 5;
multiplyAssign *= 2; // multiplyAssign = multiplyAssign * 2
console.log(multiplyAssign); // 10


// 除算代入演算子(/=)
let divideAssign = 10;
divideAssign /= 2; // divideAssign = divideAssign / 2
console.log(divideAssign); // 5




// 等価演算子(==)
console.log(5 == '5'); // true(型を変換して比較)

// 厳密等価演算子(===)
console.log(5 === '5'); // false(型も含めて比較)



// in 演算子
let obj = { name: "Alice", age: 25 };
console.log("name" in obj); // true
console.log("gender" in obj); // false




// instanceof 演算子
function Person(name) {
    this.name = name;
}
let alice = new Person("Alice");
console.log(alice instanceof Person); // true
console.log(alice instanceof Object); // true





// 左シフト演算子(<<)
let leftShift = 2 << 1; // 2を1ビット左にシフト、結果は4
console.log(leftShift); // 4

// 右シフト演算子(>>)
let rightShift = 4 >> 1; // 4を1ビット右にシフト、結果は2
console.log(rightShift); // 2



delete演算子


・オペランドに指定した配列の要素やオブジェクトプロパティを削除する
変数や関数は削除できない
・削除成功 -> true, 失敗-> false
・配列の1つの項目を消しても配列の要素数は変わらない

var emp = {no: 1, name: "yamada"};
var empNo = emp.no;

delete emp.no;
delete empNo;


console.log(emp.no); // undefined
console.log(empNo); // 1





delete emp;  // 削除されない
console.log(emp); // { name: 'yamada' }


var array = [1, 2, 3];

delete array[0];


console.log(array[0]); // undefined
console.log(array.length); // 3


instanceof演算子

var val1 = "hello"; // プリミティブ型
var val2 = new String("hello"); // ラッパーオブジェクト


console.log(val1 instanceof Object); // false 
console.log(val2 instanceof Object); // true

in演算子

var cat = {name: "ラム", type:"エキゾチックショートヘア"};
console.log("name" in cat); // true   nameがある
console.log("bark" in cat); // false   barkがない

cat.bark = function() {
    console.log("myao");
};

console.log("bark" in cat); // 今度はtrue


typeof演算子

var str1 = "hello"; // 文字列型
var str2 = new String("hello"); // オブジェクト型
var arr = ["banana", "orange"]; // オブジェクト型

console.log(typeof str1); // string
console.log(typeof str2); // object
console.log(typeof arr); // object


void演算子

undefined を返すために使用される演算子

使用例: リンクのクリックを無効化し、JavaScriptの処理を実行させる

・イベントハンドラ内でページのリダイレクトを防ぐ
・リンクをクリックしてもページがリダイレクトしないようにする

//数値を評価するが結果を無視する
let result = void 42;
console.log(result); // undefined





// 関数呼び出しの結果を無視する
function sayHello() {
    return "Hello!";
}
let greeting = void sayHello();
console.log(greeting); // undefined



++数値、数値++、数が格納される順番


let x = 5;
let y = ++x; // 先に x をインクリメントしてから y に代入

console.log(x); // 6
console.log(y); // 6






let a = 5;
let b = a++; // 先に a の現在の値を b に代入してから a をインクリメント

console.log(a); // 6
console.log(b); // 5









let i = 3;
let j = 3;

console.log(++i); // 前置インクリメント:4を返す
console.log(j++); // 後置インクリメント:3を返す

console.log(i); // 4(インクリメント後の値)
console.log(j); // 4(インクリメント後の値)

== と ===


== は値の型を強制的に変換してから比較する(型変換あり)
=== は値と型の両方を厳密に比較する(型変換なし)


== は「等価演算子」と呼ばれ、比較する値の型を強制的に変換してから比較する

5と文字列の'5'0falsenullundefined、そして空文字列''falseは、それぞれ型変換されて比較する

console.log(5 == '5'); // true
console.log(0 == false); // true
console.log(null == undefined); // true
console.log('' == false); // true

=== は「厳密等価演算子」と呼ばれ、型変換はしない
比較する値の型と値が両方とも同じ場合にのみtrueを返す

5と文字列の'5'0falsenullundefined、そして空文字列''falseは、型が異なるためfalseを返す

console.log(5 === '5'); // false
console.log(0 === false); // false
console.log(null === undefined); // false
console.log('' === false); // false




戻り値が無い関数をconsole.logするとundefinedとなる

以下の関数はreturnしてないため結果は、
hello undefined
  となる

function hello() {
    console.log("hello");
}

console.log(hello());



ガーベージコレクション

・不要になったメモリを自動的に解放する仕組み

・ガーベージコレクタというソフトウェアが行う

・ガーベージコレクションの対象
割り当てられたメモリが参照されなくなる


strictモード

strictモードのルール

・関数で同じ引数名を指定できない
宣言していない変数を使用できない
オブジェクトに同じ名前のプロパティ及びメソッドを定義できない
delete演算子で変酢や関数を削除できない
with文を使用できない

strictモードを有効にする記述
"use strict";


・関数で同じ引数名を指定できない

'use strict';
function sum(a, a) {
  return a + a;
}
// SyntaxError: Duplicate parameter name not allowed in this context

宣言していない変数を使用できない

'use strict';
function showValue() {
  value = 10; // value は宣言されていない
}

showValue();
// ReferenceError: value is not defined

・オブジェクトに同じ名前のプロパティ及びメソッドを定義できない

'use strict';
var obj = {
  prop: 42,
  prop: 43
};

// SyntaxError: Duplicate data property in object literal not allowed in strict mode



delete演算子で変数や関数を削除できない

'use strict';
var myVar = 10;
delete myVar;
// SyntaxError: Delete of an unqualified identifier in strict mode.

・with文を使用できない

'use strict';
var obj = {a: 1, b: 2};
with (obj) {
  console.log(a + b);
}
// SyntaxError: Strict mode code may not include a with statement


URLエンコード/デコード

URLとそのコンポーネントのエンコードやデコードを行う

encodeURIComponent()
 引数の文字列をエンコードする
encodeURI()
 引数の文字列をURLエンコードする
decodeURIComponent()
 URLエンコードされた文字列をデコードする
decodeURI()
 URLエンコードされた文字列をデコードする

var myParam = 'こんにちは/さようなら?#&=';
var encodedParam = encodeURIComponent(myParam);
console.log(encodedParam); // 出力: %E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF%2F%E3%81%95%E3%82%88%E3%81%86%E3%81%AA%E3%82%89%3F%23%26%3D


var url = 'http://example.com/こんにちは?name=太郎&city=東京';
var encodedUrl = encodeURI(url);
console.log(encodedUrl); // 出力: http://example.com/%E3%81%93%E3%82%93%E3%81%AB%E3%81%A1%E3%81%AF?name=%E5%A4%AA%E9%83%8E&city=%E6%9D%B1%E4%BA%AC


var decodedParam = decodeURIComponent(encodedParam);
console.log(decodedParam); // 出力: こんにちは/さようなら?#&=


var decodedUrl = decodeURI(encodedUrl);
console.log(decodedUrl); // 出力: http://example.com/こんにちは?name=太郎&city=東京













条件式

switch / if / for / while / do-while

構文


if(条件式1) {
    
} else if(条件式2) {
    
} else {
    
}






switch (式) {
    case1:
        break;
    case2:
        break;
    default:
        すべての条件に当てはまらない場合
}






for(初期値; 条件式; 増減式) {
    
}





while(条件式) {

}






do {
    
} while (条件);


var num = 10;
if(num % 2 == 0) {
  console.log(num + "は偶数");  
} else {
  console.log(num + "は奇数");  
}
var num = 1;

switch (num) {
    case 1:
        console.log("1が入力された");
        break;
    case 2:
        console.log("2が入力された");
        break;
    default:
        console.log("1と2以外が入力された");
}
for (var i = 0; i < 3; i++) {
    console.log(i);
}






// 0~9を出力

for (var i = 0; i < 10; i++) {
    console.log(i);
}


for (var i = 0; i <= 9; i++) {
    console.log(i);
}
var num = 0;
while (num < 100) {
    if (num > 55) {
        num += 6;
    }
    num += 11;
}

console.log(num); // 100
var num = 100;
do {
    if (num > 55) {
        num += 6;
    }
    num += 11;
} while (num < 100);

console.log(num); // 117


switchの注意点はcaseにはbreakを付けること

var cat = ["ラム", "エキゾチックショートヘア", 1.4];

// 要素番号が表示される
// 表示される順番は保証されない
for (var data in cat) {
    console.log(data);
}


// 配列の値が表示される
for (var data in cat) {
    console.log(cat[data]);
}



// break その時点で繰り返しから抜ける
// continue 現在の処理を中断し、次の要素を処理する


var scores = [70, 60, 30, 90, 40, 100];

console.log(calc1(scores)); // 130
console.log(calc2(scores)); // 320


function calc1 (arr) {
    var result = 0;
    
    for (var i = 0; i < arr.length; i++) {
        if (arr[i] < 50) {
            break;
        }
        result += arr[i];
    }
    
    return result;
}

function calc2 (arr) {
     var result = 0;
    
    for (var i = 0; i < arr.length; i++) {
        if (arr[i] < 50) {
            continue;
        }
        result += arr[i];
    }
    
    return result;
}




try - catch - finally

var result = {
    
};

var data = '{"foo": "bar"}'; // 正しいJSONフォーマット
var invalidData = "foot=bar"; // 不正なJSONフォーマット






try {
    result = JSON.parse(data);
} catch (err) {
    console.log(err);
} finally {
    console.log(result);
}







try {
    result = JSON.parse(invalidData);
} catch (err) {
    console.log(err);
} finally {
    console.log(result);
}



関数

無名関数: 名前がなく、変数やプロパティに代入して使用される
        関数式やコールバックとしてよく使われる

名前付き関数: 名前があり、関数宣言として定義される
      どこからでも呼び出せる

即時実行関数(IIFE): 定義と同時に実行される関数
          通常はスコープを分離するために使われる。


// 関数名を付ける場合
function add(x, y) {
    return x + y;
}

console.log(add(100, 200));




// 無名関数
var add2 = function (x, y) {
    return x + y;
}

console.log(add2(100, 200));




// 即時実行関数
(function add(x, y) {
    console.log(x + y);
}) (100, 200);



Function.call()
call()を使えば、一度定義した関数を別のオブジェクトで再利用できる

function Car(speed, fuel) {
    this.speed = speed;
    this.fuel = fuel;
}

function Truck(speed, fuel, loadage) {
    Car.call(this, speed, fuel); // 関数名.call()
    this.loadage = loadage;
}


var t1 = new Truck(40, 20, 30); // Truck { speed: 40, fuel: 20, loadage: 30 }




変数のスコープ / 関数の呼び出し

var val = 100;

function increment(val) {
    return ++val;
}

console.log(increment(val)); // 101
console.log(val); // 100



引数の値がオブジェクト型の場合は、参照先(アドレス値)がコピーされる
関数内で引数を変更する処理を行うと、元の値も変更される

var scores = [70, 30, 50, 80];

function sortScores(val) {
    return val.sort();
}

console.log(sortScores(scores)); // [ 30, 50, 70, 80 ]
console.log(scores); // [ 30, 50, 70, 80 ]



オブジェクトの生成方法

// {}の中でプロパティ名(キー名)と値を指定する
var obj1 = {name: "ラム"};

// プロパティ名(キー名)は文字列でも指定できる
var obj2 = {"name": "ラム"};

// 存在していないプロパティ名に値を格納されると、オブジェクトにプロパティが生成される
var obj3 = {}; obj3.name = "ラム";

// {}の中に変数を指定すると変数名がプロパティ名となる
var name = "ラム"; 
var obj4 = {name};


間違った生成
これは変数名に「.」を含んでいる

var cat.name = "ラム";


オブジェクトのプロパティにアクセスする方法

var cat = {name: "ラム"};



// 1)
cat.name

// 2)
cat["name"]



var cat = {name: "ラム", type: "エキゾチックショートヘア"};
cat.age = 1.4;
cat[222] = "猫の日";
cat.type = null;



// { '222': '猫の日', name: 'ラム', type: null, age: 1.4 }
console.log(cat);



コンストラクタ関数を用いたオブジェクトの生成

function Cat(name, type) {
    this.name = name;
    this.type = type;
}

var myCat = new Cat("ラム", "エキゾチックショートヘア");
var sosekiCat = new Cat("吾輩", "不明");

console.log(myCat.name); // ラム


class と constructor を用いたオブジェクトの生成

class Cat {
    constructor(name, type) {
        this.name = name;
        this.type = type;
    }
}



var myCat = new Cat("ラム", "エキゾチックショートヘア");
var sosekiCat = new Cat("吾輩", "不明");

console.log(myCat.name); // ラム


new 演算子 
コンストラクタ関数からオブジェクトを生成する演算子



プロトタイプチェーン

JavaScriptはプロトタイプ指向プログラミング言語

オブジェクトの既定のプロトタイプの確認

var cat = {};
console.log(cat.__proto__ == Object.prototype); // true


// プロトタイプに定義されたメソッドの呼び出し
var cat = {name: "ラム"};
console.log(cat.hasOwnProperty("name")); // true
console.log(cat.hasOwnProperty("age")); // false



// オブジェクトにメソッドを直接定義する例
function Cat() {
    this.play = function() {
        return "猫じゃらし";
    };
}

var cats = [new Cat(), new Cat(), new Cat()];
console.log(cats);
console.log(cats[0].play()); // 猫じゃらし


// オブジェクトのプロトタイプにメソッドを追加する
function Cat() {}
Cat.prototype.play = function() {
    return "猫じゃらし";
};

var cats = [new Cat(), new Cat(), new Cat()];
console.log(cats);
console.log(cats[0].play()); // 猫じゃらし


Object.prototype

JavaScriptの全てのオブジェクトの既定のプロトタイプ


protoyypeプロパティ

// プロトタイプへのメソッド追加
function Cat() {}
Cat.prototype.play = function() {
    return "猫じゃらし";
};


// プロトタイプの書き換え
function Animal() {}
function Cat() {}
Cat.prototype = Animal;


プロパティのシャドーイング

function Animal(name) {
    this.name = name;
}

// 全てのanimalsの項目のtypeがcatになる
Animal.prototype.type = "cat";

var animals = [new Animal("ラム"), new Animal("モカ"), new Animal("モモ")];

// animals[1].typeだけdogになる
animals[1].type = "dog";


// cat dog cat
for (let animal of animals) {
    console.log(animal.type);
}


thisキーワード

グローバル実行コンテキスト

console.log(this === window); // true

関数コンテキスト

// 非strictモードでの呼び出し
function useThis() {
    console.log(this === window); // true
}

useThis();



// strictモードでの呼び出し
function useThis() {
    "use strict";
    console.log(this === undefined); // true
}

useThis();




// オブジェクトのメソッド
var cat = {
    name: "ラム",
    greet: function() {
        return this.name + "です";
    }
};

console.log(cat.greet()); // ラムです



// コンストラクタ内
function Cat(name, type) {
    this.name = name;
}

var myCat = new Cat("ラム");






// コールバック関数
var cat = {
    name: "ラム",
    greet: function() {
        return this.name + "です";
    }
};

cat.greet();
setTimeout(cat.greet, 500);


スコープ

プログラム内における変数や関数の有効範囲のこと


グローバルスコープ
  ページ内の全ての場所から呼び出して使用できる

ローカルスコープ

  関数内でのみ呼び出して使用できる

ブロックスコープ
  制御構文内でのみ呼び出して使用できる



グローバルスコープとローカルスコープで変数名が同じ場合、ローカルのほうが優先される

print()ではvalに値を格納する前に使用しているのでundefinedとなる


巻き上げ: 関数内では、関数の最後にvarで変数を宣言しても、最初に宣言したものとして使用される


ただし、巻き上げは値の初期化は出来ない、よってconsole.log(val)の時点では値が設定されてない。

var val = "A";

function print() {
    console.log(val);
    var val = "B";
    return val;
}

console.log(print());
console.log(val);



結果
undefined
B
A


スコープチェーン:

関数内に関数を定義するなどスコープを入れ子にした場合、
内側のスコープから外側のスコープに変数定義を検索する仕組み

var global = "Global";

function outerScope() {
    var local = "Outer";
    function innerScope() {
        var local = "Inner"; // ここでlocalにInnerが入る
        console.log(local); 
        console.log(global);
    }
    
    innerScope(); // Inner, Global と表示
    console.log(local); // Outerと表示
                       // innerScope()内の変更は影響してない
    console.log(value); // ReferenceError と表示
}

outerScope();


JavaScriptでは、
varで変数を宣言したら、ブロック内でもグローバルスコープとなる

有効範囲をブロックスコープにするならletを使う

var score = 95;

if (score >= 70) {
    var message = "合格です";
}

console.log(message); // 合格です と表示される

上記を、let message と宣言したらエラーになる



関数宣言の巻き上げ

1) 
関数宣言全体で巻き上げられる


func1();

function func1() {
    console.log("関数1"); // 関数1 と表示
}

2) 
TypeErrorが発生する

変数に関数リテラルを代入する場合は、変数宣言のみ巻き上げられる


func2()で呼び出し後に、関数リテラルの代入が行われる
func2の宣言時は、値はundifinedのまま


func2();

var func2 = function () {
    console.log("関数2");
}




var value = "グローバル";

function func1() {
    console.log(value);
}

function func2() {
    var value = "ローカル";
    func1();
}

func2(); // グローバル と表示される



----------------



var value = "グローバル";

function func1() {
    console.log(value);
}

function func2() {
    var value = "ローカル";
    
    console.log(value);  // ローカルで宣言したvalueが表示される
    
    func1();
}

func2(); // ローカル グローバル と表示される



以下はfuncB()でエラーが発生する
funcC()でfuncB()を参照できないため

  1. 関数funcBのスコープの問題: funcBfuncAの中で定義されてるが、funcAの外から直接呼び出せない。
    funcBfuncAの外で定義する必要がある。

  2. 変数messageのスコープの問題: 関数funcCの中で定義されたmessageが、他の関数で参照されるmessageと異なるため、意図した挙動にならない。

var message = "Hello";

var funcA = function() {
    function funcB () {
        console.log(message);
    }
    console.log(message);
};

function funcC(f) {
    var message = new String("bye");
    f();
    funcA();
    funcB();
} 

funcC(funcA);



正しく動作するためには以下のように書き換える

  • funcBfuncAの外に定義

  • funcCの中でmessageを一時的に変更し、元のmessageに戻すようにする。
    これにより、funcAfuncBmessageを参照するときに正しい値を取得できる。

var message = "Hello";

var funcB = function() {
    console.log(message);
};

var funcA = function() {
    console.log(message);
    funcB();
};

function funcC(f) {
    var localMessage = "bye";
    var originalMessage = message;
    message = localMessage;
    f();
    message = originalMessage;
    funcA();
}

funcC(funcA);




クロージャ

関数と関数が宣言された環境の組み合わせ


関数を入れ子にすることで、内部の関数が、外部のスコープで宣言された変数への参照を保持する



・変数testがclosure()関数を参照する
・closure()関数は変数catNameを参照する
・closure()関数からの参照が残るので、
 変数catNameはガーベージコレクションの覇気の対象にならず残り続ける


function myCatName() {
    var catName = "Lum";
    
    function closure() {
        return catName;
    }
    
    return closure;
}

var test = myCatName();

console.log(test()); // Lum と表示


with文

スコープチェーンを拡張する

withにオブジェクト名を指定すれば、withのブロック内で指定されたオブジェクト名の記述を省略できる

・withは使用された識別子をスコープチェーン上で検索する
・識別子の検索は、
 指定されたオブジェクト、スコープチェーンの順で実行する
・strictモードでは使用できない


// withを使わない例
document.querySelector("#element").style.color = "#fff";
document.querySelector("#element").style.fontSize = "15px";
document.querySelector("#element").style.fontWeight = "bold";





// withを使う例
with(document.querySelector("#element").style) {
    color = "#fff";
    fontSize = "15px";
    fontWeight = "bold";
}





parseInt

文字列を数値に変換する
第1引数に文字列、第2引数に解析するときの基数
・第2引数は省略可能
・第1引数が「0x」で始まる場合は16進数、そうでない場合は10進数を使う
・解析できない文字列はNaNを返す
・小数点の文字列が渡されたら、小数点以下を切りすてて数値化

全て、「15」を返す


parseInt("15");
parseInt("0xf");
parseInt("15.8");





WebブラウザにおけるJavaScript API


イベント: ページ上で発生する動作

フォームに関するイベント

blur
change
contextmenu
focus
input
invalid
select
submit
formchange
forminput

document.addEventListener('DOMContentLoaded', (event) => {
    const form = document.getElementById('exampleForm');
    const textInput = document.getElementById('textInput');
    const changeInput = document.getElementById('changeInput');
    const invalidInput = document.getElementById('invalidInput');
    const selectInput = document.getElementById('selectInput');

    // blur event
    textInput.addEventListener('blur', (event) => {
        console.log('Blur event triggered');
    });

    // change event
    changeInput.addEventListener('change', (event) => {
        console.log('Change event triggered');
    });

    // contextmenu event
    textInput.addEventListener('contextmenu', (event) => {
        console.log('Context menu event triggered');
    });

    // focus event
    textInput.addEventListener('focus', (event) => {
        console.log('Focus event triggered');
    });

    // input event
    textInput.addEventListener('input', (event) => {
        console.log('Input event triggered');
    });

    // invalid event
    invalidInput.addEventListener('invalid', (event) => {
        console.log('Invalid event triggered');
    });

    // select event
    selectInput.addEventListener('select', (event) => {
        console.log('Select event triggered');
    });

    // submit event
    form.addEventListener('submit', (event) => {
        event.preventDefault(); // Prevent the default form submission
        console.log('Submit event triggered');
    });

    // formchange event
    form.addEventListener('change', (event) => {
        console.log('Form change event triggered');
    });

    // forminput event
    form.addEventListener('input', (event) => {
        console.log('Form input event triggered');
    });
});


キーボード操作のイベント

keydown
keypress
keyup


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Keyboard Events Example</title>
</head>
<body>
    <form id="keyboardForm">
        <input type="text" id="keyboardInput" placeholder="Type something...">
    </form>

    <script src="keyboardEvents.js"></script>
</body>
</html>






document.addEventListener('DOMContentLoaded', (event) => {
    const keyboardInput = document.getElementById('keyboardInput');

    // keydown event
    keyboardInput.addEventListener('keydown', (event) => {
        console.log('Keydown event triggered:', event.key);
    });

    // keypress event
    keyboardInput.addEventListener('keypress', (event) => {
        console.log('Keypress event triggered:', event.key);
    });

    // keyup event
    keyboardInput.addEventListener('keyup', (event) => {
        console.log('Keyup event triggered:', event.key);
    });
});


マウス操作のイベント

click
dbclick
drag
dragend
dragenter
dragleave
dragover
dragstart
drop
mousedown
mousemove
mouseout
mouseover
mouseup
mousewheel
scroll





loadイベント

ページや要素の読み込みが完了した時に発生する

・Documentオブジェクトはonloadイベントハンドラをプロパティとして持つ
・windowオブジェクトのloadイベント発生時には、ページ内の全ての画像は読み込まれている
・windwoオブジェクトのloadイベント発生時は、ページ内の全てのDOMは読み込まれている










グラフィックス・アニメーション


Canvas(2D)



SVG




Timing control for script-based animations







マルチメディア


メディア要素のAPI     HTMLMediaElement

video要素やaudio要素をJavaScriptから操作する際の共通の機能を定義する

autoplay
controls
currentTime
ended
error
loop
networkState
paused
played
preload
duration
volume
playbackRate
muted

play()
pause()
load()


onplay
onplaying
ontimeupdate
onpause
onwaiting
onstalled
onended
onerror
onabort
onloadstart
onprogress
onloadeddata





ストレージ


Web Storage

ブラウザに「キーと値の組み合わせ」でデータを保持する仕組み。

Web Storageに保存できるデータは「文字列のみ」

画像データを保存するなら Data URIスキームなどに変換する

Web Storageの種類:
 データの保存期間が違う。
・localStorage
 ブラウザが閉じられてもデータを保持する
 ウィンドウやタブ間でデータを共有できる
・sessionStorage
 ブラウザが閉じられると同時にデータが消失する
 新しいウィンドウやタブを開くと新しいセッションが開始する

strageオブジェクトのプロパティ、メソッド

length
 保存されているデータ(キー、値)の数
key()
 指定した数値のキーを返す
getItem()
 指定したキーの名称に対する値を返す
setItem()
 指定したキーの名称と値を追加する
removeItem()
 指定したキーのデータを削除する
clear()
 ストレージからすべてのデータを削除する










Indexed Database API

構造化されたデータを保存する仕組み

Indexed Database APIの特徴:
・RDBのようにインデックスによる検索やトランザクションに取る安全な操作が出来る
・SQLではなくJavaScriptで操作する
・格納できる値の種類は、
 文字列
 ファイル
 blob(画像データ)
・格納処理は非同期で実行される
・ブラウザが閉じられても、明示的にデータを破棄しない限り、永続的にデータを保持する


例えば以下のようなwebアプリケーションを新規に作成するときに、
以下の要件の技術が必要なら、Indexed Database APIを使う
・大容量のデータを保存する
・データを永続保存する
・ファイルやblobを保存する
・パフォーマンスが求められる


Web SQLは使用策定が中止されているため新規作成時には向いてない



File API

JavaScriptからローカルに保存されているファイルにアクセスできる

扱えるデータ:
・input要素によって選択されたファイル
・ドラッグアンドドロップ操作によるもの
・ユーザが指定したもの

FileReaderオブジェクトを利用してテキストデータやバイナリデータを扱ったり、ファイルの読み込み状態を監視する


File APIのファイルリスト取得

ユーザがinput要素に指定したデータはFileListオブジェクトで管理される

FileListオブジェクト
・inputオブジェクトのfilesプロパティで取得できる
・ユーザが指定したファイルをFileオブジェクトとして管理する配列のように扱える

・複数のファイルが選択されている時は、files[要素数]で各ファイルにアクセスできる

FileListオブジェクトのプロパティ、メソッド

length
item()

Blogオブジェクトのプロパティ、メソッド

size
type
close()
slice()

Fileオブジェクトのプロパティ、メソッド

name
lastModified

FileReaderオブジェクト

ユーザが指定したファイルを非同期でメモリ上に読み込む




FileReaderオブジェクトのプロパティ、メソッド、イベントハンドラ

readyState
result
error


abort()
readAsArrayBuffer()
readyAsDataURL()
readAsText()

onabort
onerror
onload
onloadstart
onloaded
onprogress

FileReader.readyStateプロパティ

EMPTY(0)
LOADING(1)
DONE(2)









バイナリデータ





通信


WebSocket

ブラウザ-サーバ間で双方向の常時接続通信を行う技術

・WebSocketを用いるとXMLHttpRequestによるロングポーリングより効率的に双方向通信できる
・WebSocketプロトコルを用いてWebSocket通信を行う

・URLスキームはws, wssのどちらか
・HTTPとは異なるプロトコルなのでブラウザ、サーバサイドも
 WebSocketに対応した製品が必要になる
・サーバサイドがWebSocketに対応してない場合は、アーキテクチャを変更する

・WebSocketによる通信を行うには、WebSocketオブジェクトを生成する
生成時のパラメータには通信先のURLを渡す。


・URLの構造
スキーム://ホスト名:ポート番号/ディレクトリ/ファイル名


・スキームにws, wss以外を指定するとSyntaxErrorが発生する

・WebSocketは常時接続をしていてリアルタイムアプリケーションに向いている

しかし、クライアント数が増えるとサーバ側の負荷も高まる








JavaScriptでWebSocketを生成する例

// WebSocketサーバーのURLを指定します
const wsUrl = 'wss://example.com/socket'; // wssはWebSocket Secureを意味します

// WebSocketオブジェクトを生成します
const socket = new WebSocket(wsUrl);

// 接続が開かれたときに呼び出されるイベントハンドラ
socket.onopen = function(event) {
    console.log('WebSocket connection opened:', event);

    // サーバーにメッセージを送信します
    socket.send('Hello Server!');
};

// メッセージを受信したときに呼び出されるイベントハンドラ
socket.onmessage = function(event) {
    console.log('Message received from server:', event.data);
};

// 接続が閉じられたときに呼び出されるイベントハンドラ
socket.onclose = function(event) {
    console.log('WebSocket connection closed:', event);
    console.log('Close code:', event.code);
    console.log('Close reason:', event.reason);
};

// エラーが発生したときに呼び出されるイベントハンドラ
socket.onerror = function(error) {
    console.error('WebSocket error:', error);
};

// サーバーにメッセージを送信する関数
function sendMessage(message) {
    if (socket.readyState === WebSocket.OPEN) {
        socket.send(message);
    } else {
        console.error('WebSocket is not open. ReadyState:', socket.readyState);
    }
}

// WebSocket接続を閉じる関数
function closeConnection() {
    if (socket.readyState === WebSocket.OPEN || socket.readyState === WebSocket.CONNECTING) {
        socket.close(1000, 'Closing connection normally'); // 1000は通常のクローズコード
    } else {
        console.error('WebSocket is already closed. ReadyState:', socket.readyState);
    }
}

// 例: 5秒後にメッセージを送信し、10秒後に接続を閉じる
setTimeout(() => sendMessage('Ping from client'), 5000);
setTimeout(() => closeConnection(), 10000);

WebSocketの生成

const socket = new WebSocket(wsUrl);

イベントハンドラの設定:

onopen: WebSocket接続が開かれたときに呼び出される。

onmessage: サーバーからメッセージを受信したときに呼び出される

onclose: WebSocket接続が閉じられたときに呼び出される

onerror: WebSocketエラーが発生したときに呼び出される



メッセージの送信:

socket.send('Hello Server!');

接続の閉じ方:

socket.close(1000, 'Closing connection normally');




WebSocket関連の主なイベント

open
 接続が開始した際のイベント
close
 接続が閉じた際のイベント
message
 サーバからのデータを受信した際のイベント
error
 エラーが発生した際のイベント

WebSocketの主なメンバ

send()
 データを送信するメソッド
close()
 通信を切断するメソッド
bufferedAmount()
 send()で送信するデータのうち、未送信量を表す
url
 通信先の絶対URLを表すプロパティ
readyState
 通信状態を表すプロパティ




XMLHttpRequest

ブラウザ-サーバ間でHTTP通信を行うための技術

・非同期通信ができて、Ajaxを実装するときに用いられている
・XMLHttpRequestオブジェクトを生成することで、XMLHttpRequest通信を実装できる






<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>XMLHttpRequest Example</title>
    <script>
        function sendData() {
            // データを文字列として定義
            var data = "This is the data to send";

            // 新しいXMLHttpRequestオブジェクトを作成
            var xhr = new XMLHttpRequest();

            // リクエストの設定
            xhr.open("POST", "https://example.com/api/endpoint", true);

            // 必要に応じてリクエストヘッダーを設定
            xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

            // リクエストの状態が変わった時に呼ばれる関数
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4) {
                    if (xhr.status === 200) {
                        // リクエストが成功した場合の処理
                        console.log("Response received:", xhr.responseText);
                    } else {
                        // リクエストが失敗した場合の処理
                        console.error("Error:", xhr.statusText);
                    }
                }
            };

            // データの送信
            xhr.send("data=" + encodeURIComponent(data));
        }
    </script>
</head>
<body>
    <h1>XMLHttpRequest Example</h1>
    <button onclick="sendData()">Send Data</button>
</body>
</html>


XMLHttpRequestのキャッシュ

open()
  リクエストを初期化する

setRequestHeader()
  リクエストヘッダを指定する
  XMLHttpRequestで取得したリソースのキャッシュをさせない

send()
  サーバにリクエストする

abort()
  リクエストを中断する

timeout()
  リクエストをタイムアウトする時刻をミリ単位で指定する

withCredentials
  認証情報を使用するかBoolean値で指定する

upload
  アップロードプロセスを表す


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>XMLHttpRequest Example</title>
    <script>
        var xhr;

        function sendData() {
            // 新しいXMLHttpRequestオブジェクトを作成
            xhr = new XMLHttpRequest();

            // URLを設定
            var url = "https://example.com/api/endpoint";

            // リクエストの設定
            xhr.open("POST", url, true); // メソッド、URL、非同期通信の設定

            // リクエストヘッダを設定
            xhr.setRequestHeader("Content-Type", "application/json");

            // withCredentials プロパティを true に設定(認証情報を使用)
            xhr.withCredentials = true;

            // timeout プロパティを設定(タイムアウトをミリ秒単位で設定)
            xhr.timeout = 5000; // 5秒

            // リクエストの状態が変わった時に呼ばれる関数
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4) {
                    if (xhr.status === 200) {
                        // リクエストが成功した場合の処理
                        console.log("Response received:", xhr.responseText);
                    } else {
                        // リクエストが失敗した場合の処理
                        console.error("Error:", xhr.statusText);
                    }
                }
            };

            // タイムアウト時に呼ばれる関数
            xhr.ontimeout = function () {
                console.error("Request timed out.");
            };

            // エラー時に呼ばれる関数
            xhr.onerror = function () {
                console.error("Request error.");
            };

            // データの送信
            var data = JSON.stringify({ message: "Hello, server!" });
            xhr.send(data);
        }

        function abortRequest() {
            if (xhr) {
                xhr.abort(); // リクエストを中断
                console.log("Request aborted.");
            }
        }

        // ファイルのアップロード時の処理
        function uploadFile(file) {
            var uploadXhr = new XMLHttpRequest();
            var url = "https://example.com/api/upload";

            uploadXhr.open("POST", url, true);
            uploadXhr.setRequestHeader("Content-Type", "multipart/form-data");

            // ファイルのアップロード進捗を監視
            uploadXhr.upload.onprogress = function (event) {
                if (event.lengthComputable) {
                    var percentComplete = (event.loaded / event.total) * 100;
                    console.log("Upload progress:", percentComplete + "%");
                }
            };

            uploadXhr.onreadystatechange = function () {
                if (uploadXhr.readyState === 4) {
                    if (uploadXhr.status === 200) {
                        console.log("Upload complete:", uploadXhr.responseText);
                    } else {
                        console.error("Upload error:", uploadXhr.statusText);
                    }
                }
            };

            uploadXhr.send(file);
        }

        function handleFileSelect(event) {
            var file = event.target.files[0];
            if (file) {
                uploadFile(file);
            }
        }
    </script>
</head>
<body>
    <h1>XMLHttpRequest Example</h1>
    <button onclick="sendData()">Send Data</button>
    <button onclick="abortRequest()">Abort Request</button>
    <input type="file" id="fileInput" />
    <script>
        document.getElementById('fileInput').addEventListener('change', handleFileSelect, false);
    </script>
</body>
</html>


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>XMLHttpRequest No Cache Example</title>
    <script>
        function fetchData() {
            // 新しいXMLHttpRequestオブジェクトを作成
            var xhr = new XMLHttpRequest();

            // 現在の日時を取得して一意のクエリパラメータを生成
            var timestamp = new Date().getTime();
            var url = "https://example.com/api/endpoint?nocache=" + timestamp;

            // リクエストの設定
            xhr.open("GET", url, true);

            // リクエストの状態が変わった時に呼ばれる関数
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4) {
                    if (xhr.status === 200) {
                        // リクエストが成功した場合の処理
                        console.log("Response received:", xhr.responseText);
                    } else {
                        // リクエストが失敗した場合の処理
                        console.error("Error:", xhr.statusText);
                    }
                }
            };

            // データの送信
            xhr.send();
        }
    </script>
</head>
<body>
    <h1>XMLHttpRequest No Cache Example</h1>
    <button onclick="fetchData()">Fetch Data</button>
</body>
</html>


XMLHttpRequestの主なイベントハンドラ

onreadystatechange
onloadstart
onprogress
onabort
onerror
onload
ontimeout
onloadend


XMLHttpRequestの主なレスポンス関連のメンバ

getResponseHeader()
getAllResponseHeaders()
overrideMimeType()
status
statusText
responseType
response
responseText
responseXML



XMLHttpRequest


XMLHttpRequest



Server-Sent Events







デバイスアクセス


Geolocation API

ユーザの位置情報を取得するAPI

特徴
・位置情報の取得方法を特定していない
 実際にはGPS, IPアドレス、無線LAN、wifiから位置情報を取得する
・ユーザの許可がないと位置情報を取得できない
・位置情報の精度、位置情報取得にかかる時間は一定でない



Geolocationオブジェクト
デバイスの位置を取得する機能

getCurrentPosition()
 デバイスの現在位置を取得。
 位置情報を取得すると引数に指定したコールバック関数が呼び出される
watchPosition()
 デバイスの位置情報を監視
 位置情報が変化すると引数にしたコールバック関数が呼び出される
clearWatch()
 取得中のデバイスの監視状況をクリアする
 



Geolocationオブジェクトを使って現在位置を取得する例

<!DOCTYPE html>
<html>
<head>
    <title>Geolocation API Example</title>
</head>
<body>
    <h1>Geolocation API Example</h1>
    <button onclick="getLocation()">現在位置を取得</button>
    <p id="status"></p>
    <p id="location"></p>

    <script>
        function getLocation() {
            const status = document.getElementById('status');
            const location = document.getElementById('location');

            if (navigator.geolocation) {
                status.textContent = '現在位置を取得しています...';
                navigator.geolocation.getCurrentPosition(success, error);
            } else {
                status.textContent = 'Geolocation はこのブラウザでサポートされていません。';
            }

            function success(position) {
                const latitude = position.coords.latitude;
                const longitude = position.coords.longitude;
                status.textContent = '現在位置の取得に成功しました。';
                location.textContent = `緯度: ${latitude} 経度: ${longitude}`;
            }

            function error() {
                status.textContent = '現在位置の取得に失敗しました。';
            }
        }
    </script>
</body>
</html>

getCurrentPosition の使用例

<!DOCTYPE html>
<html>
<head>
    <title>Get Current Position</title>
</head>
<body>
    <h1>Get Current Position Example</h1>
    <button onclick="getCurrentLocation()">現在位置を取得</button>
    <p id="status"></p>
    <p id="location"></p>

    <script>
        function getCurrentLocation() {
            const status = document.getElementById('status');
            const location = document.getElementById('location');

            if (navigator.geolocation) {
                status.textContent = '現在位置を取得しています...';
                navigator.geolocation.getCurrentPosition(success, error);
            } else {
                status.textContent = 'Geolocation はこのブラウザでサポートされていません。';
            }

            function success(position) {
                const latitude = position.coords.latitude;
                const longitude = position.coords.longitude;
                status.textContent = '現在位置の取得に成功しました。';
                location.textContent = `緯度: ${latitude} 経度: ${longitude}`;
            }

            function error() {
                status.textContent = '現在位置の取得に失敗しました。';
            }
        }
    </script>
</body>
</html>

watchPosition の使用例

<!DOCTYPE html>
<html>
<head>
    <title>Watch Position</title>
</head>
<body>
    <h1>Watch Position Example</h1>
    <button onclick="startWatching()">位置の監視を開始</button>
    <button onclick="stopWatching()">位置の監視を停止</button>
    <p id="status"></p>
    <p id="location"></p>

    <script>
        let watchId;

        function startWatching() {
            const status = document.getElementById('status');
            const location = document.getElementById('location');

            if (navigator.geolocation) {
                status.textContent = '位置の監視を開始しました。';
                watchId = navigator.geolocation.watchPosition(success, error);
            } else {
                status.textContent = 'Geolocation はこのブラウザでサポートされていません。';
            }

            function success(position) {
                const latitude = position.coords.latitude;
                const longitude = position.coords.longitude;
                location.textContent = `緯度: ${latitude} 経度: ${longitude}`;
            }

            function error() {
                status.textContent = '位置の取得に失敗しました。';
            }
        }

        function stopWatching() {
            const status = document.getElementById('status');

            if (watchId !== undefined) {
                navigator.geolocation.clearWatch(watchId);
                status.textContent = '位置の監視を停止しました。';
                watchId = undefined;
            } else {
                status.textContent = '監視している位置情報はありません。';
            }
        }
    </script>
</body>
</html>


clearWatch の使用例

<!DOCTYPE html>
<html>
<head>
    <title>Clear Watch Position</title>
</head>
<body>
    <h1>Clear Watch Position Example</h1>
    <button onclick="startWatching()">位置の監視を開始</button>
    <button onclick="stopWatching()">位置の監視を停止</button>
    <p id="status"></p>
    <p id="location"></p>

    <script>
        let watchId;

        function startWatching() {
            const status = document.getElementById('status');
            const location = document.getElementById('location');

            if (navigator.geolocation) {
                status.textContent = '位置の監視を開始しました。';
                watchId = navigator.geolocation.watchPosition(success, error);
            } else {
                status.textContent = 'Geolocation はこのブラウザでサポートされていません。';
            }

            function success(position) {
                const latitude = position.coords.latitude;
                const longitude = position.coords.longitude;
                location.textContent = `緯度: ${latitude} 経度: ${longitude}`;
            }

            function error() {
                status.textContent = '位置の取得に失敗しました。';
            }
        }

        function stopWatching() {
            const status = document.getElementById('status');

            if (watchId !== undefined) {
                navigator.geolocation.clearWatch(watchId);
                status.textContent = '位置の監視を停止しました。';
                watchId = undefined;
            } else {
                status.textContent = '監視している位置情報はありません。';
            }
        }
    </script>
</body>
</html>



Geolocationオブジェクトのコールバック関数

Geolocation APIのコールバック関数は、位置情報の取得が成功した場合(success コールバック)と失敗した場合(error コールバック)に呼び出される

getCurrentPosition のコールバック関数の例

<!DOCTYPE html>
<html>
<head>
    <title>Geolocation Example</title>
</head>
<body>
    <h1>Geolocation API Example</h1>
    <button onclick="getCurrentLocation()">現在位置を取得</button>
    <p id="status"></p>
    <p id="location"></p>

    <script>
        function getCurrentLocation() {
            const status = document.getElementById('status');
            const location = document.getElementById('location');

            if (navigator.geolocation) {
                status.textContent = '現在位置を取得しています...';
                navigator.geolocation.getCurrentPosition(successCallback, errorCallback);
            } else {
                status.textContent = 'Geolocation はこのブラウザでサポートされていません。';
            }
        }

        function successCallback(position) {
            const latitude = position.coords.latitude;
            const longitude = position.coords.longitude;
            const accuracy = position.coords.accuracy;

            const status = document.getElementById('status');
            const location = document.getElementById('location');

            status.textContent = '現在位置の取得に成功しました。';
            location.innerHTML = `緯度: ${latitude}<br>経度: ${longitude}<br>精度: ${accuracy} メートル`;
        }

        function errorCallback(error) {
            const status = document.getElementById('status');

            switch(error.code) {
                case error.PERMISSION_DENIED:
                    status.textContent = 'ユーザーが位置情報の取得を拒否しました。';
                    break;
                case error.POSITION_UNAVAILABLE:
                    status.textContent = '位置情報が利用できません。';
                    break;
                case error.TIMEOUT:
                    status.textContent = '位置情報の取得がタイムアウトしました。';
                    break;
                case error.UNKNOWN_ERROR:
                    status.textContent = '不明なエラーが発生しました。';
                    break;
            }
        }
    </script>
</body>
</html>

watchPosition のコールバック関数の例

<!DOCTYPE html>
<html>
<head>
    <title>Watch Position Example</title>
</head>
<body>
    <h1>Watch Position Example</h1>
    <button onclick="startWatching()">位置の監視を開始</button>
    <button onclick="stopWatching()">位置の監視を停止</button>
    <p id="status"></p>
    <p id="location"></p>

    <script>
        let watchId;

        function startWatching() {
            const status = document.getElementById('status');
            const location = document.getElementById('location');

            if (navigator.geolocation) {
                status.textContent = '位置の監視を開始しました。';
                watchId = navigator.geolocation.watchPosition(successCallback, errorCallback);
            } else {
                status.textContent = 'Geolocation はこのブラウザでサポートされていません。';
            }
        }

        function stopWatching() {
            const status = document.getElementById('status');

            if (watchId !== undefined) {
                navigator.geolocation.clearWatch(watchId);
                status.textContent = '位置の監視を停止しました。';
                watchId = undefined;
            } else {
                status.textContent = '監視している位置情報はありません。';
            }
        }

        function successCallback(position) {
            const latitude = position.coords.latitude;
            const longitude = position.coords.longitude;
            const accuracy = position.coords.accuracy;
            const timestamp = position.timestamp;

            const location = document.getElementById('location');
            location.innerHTML = `緯度: ${latitude}<br>経度: ${longitude}<br>精度: ${accuracy} メートル<br>タイムスタンプ: ${new Date(timestamp).toLocaleString()}`;
        }

        function errorCallback(error) {
            const status = document.getElementById('status');

            switch(error.code) {
                case error.PERMISSION_DENIED:
                    status.textContent = 'ユーザーが位置情報の取得を拒否しました。';
                    break;
                case error.POSITION_UNAVAILABLE:
                    status.textContent = '位置情報が利用できません。';
                    break;
                case error.TIMEOUT:
                    status.textContent = '位置情報の取得がタイムアウトしました。';
                    break;
                case error.UNKNOWN_ERROR:
                    status.textContent = '不明なエラーが発生しました。';
                    break;
            }
        }
    </script>
</body>
</html>


Positionオブジェクト

現在位置を表す

位置情報の取得に成功した場合に呼び出されるPositionCallback関数の引数として渡す



PositionErrorオブジェクト

位置情報の取得に失敗した場合のエラー情報を扱う

位置情報の取得に失敗した時に呼び出されるPositionErrorCallback関数の引数として渡される

プロパティ:
code
 エラーコード取得
message
 エラーメッセージを取得


Coordinatesオブジェクト

デバイスの位置、高度、精度を表す

Positionオブジェクトのcoordsプロパティで取得できる


プロパティ:
latitude
 緯度を取得(double)
longitude
 経度を取得(double)
altitude
 高度を取得(double)
accuracy
 latitudeおよびlongitudeの精度を取得(double)
altitudeAccuracy
 altitudeの精度(メートル)を取得(double)
heading
 デバイス方位(北からの角度)を取得(double)
speed
 デバイスの移動速度(メートル/秒)を取得(double)

clearWatch() メソッド

位置情報を監視する




DeviceOrientation Event

デバイスの加速度センサの方向が変更された際に発生するイベント

・デバイスの方向を取得できる
・デバイスの方向として取得される値は、
 x, y, zの3つの軸からなる座標フレームを元に計算する

x軸: スクリーンの水平面において右方向が正 
y軸: スクリーンの水平面において前方向が正
z軸: スクリーンの水平面において上方向が正



プロパティ:
alpha

 z軸を中心としたデバイスの動きを表す
 0~360
beta
 x軸を中心としたデバイスの動きを表す
 -180~180
gamma
 y軸を中心としたデバイスの動きを表す
 -90~90







デバイスの傾きの変化率は、DeviceMotionEventオブジェクトのrotationRateプロパティで取得できる













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


Web Workers

JavaScriptで並列実行するための仕様

特徴
・ワーカという処理単位を、webページの描画処理を実行するメインスレッドから分離し、バックグラウンドで実行する
・メインスレッドとワーカが並列実行する
・ワーカ内からDOMにアクセスできない
 ただし、Web Storage、XMLHtttpRequestなどは使用できる

 例えば、ワーカ内でdocumentプロパティにアクセスするとエラーになる

・メインスレッドとワーカ間でデータの送受信も出来る
 メッセージを受信するとmessageイベントが発生する

・Workerオブジェクトは、複数生成したり、Worker内で生成できる
・Web Workersは非同期で実行される


Web Workersの種類
・Dedicated Worker
・Shared Worker



Web Workersの使用方法

・Workerオブジェクトを生成する
var worker = new Worker("JSファイルのパス");
主なメソッド:

postMessage()
terminate()
oneerror
onmessage

・Web Workersを終了させる
terminate()




Web Workersを使用してバックグラウンドで処理を行う例

worker.js (Web Worker)

self.addEventListener('message', function(e) {
    const data = e.data;
    switch (data.cmd) {
        case 'start':
            self.postMessage('Worker started: ' + data.msg);
            break;
        case 'stop':
            self.postMessage('Worker stopped: ' + data.msg);
            self.close();
            break;
    }
}, false);

main.js

if (window.Worker) {
    const myWorker = new Worker('worker.js');

    myWorker.postMessage({ cmd: 'start', msg: 'Hello World' });

    myWorker.onmessage = function(e) {
        console.log('Message received from worker:', e.data);
    };

    myWorker.postMessage({ cmd: 'stop', msg: 'Goodbye' });
}




High Resolution Time API

パフォーマンス関連の情報を取得するAPI

JavaScript実行時のパフォーマンスチェックなどに活用できる

・時刻を表示する
perfomance.now()

取得できる情報の精度はマイクロ秒、単位はミリ秒

・プロセスの実行タイミング
早い順に、
redirectEnd
connectEnd
responseEnd
loadEventEnd





高解像度の現在の時刻を取得する例

const startTime = performance.now();

// Simulate some workload
for (let i = 0; i < 1000000; i++) {
    // Some calculation
}

const endTime = performance.now();
console.log(`Time taken: ${endTime - startTime} milliseconds`);


アプリケーションキャッシュ

webページのキャッシュに関する仕様

webページを構成するリソース(HTML, CSSなど)をブラウザにキャッシュする
-> オフラインでもwebページの閲覧が可能

キャッシュするには、
・マニフェストファイルで指定する
・キャッシュの更新は、マニフェストファイルの変更の有無で判断する
・リソースを更新するたびにマニフェストファイルを変更する必要がある



マニフェストファイルの記述例

example.appcache

CACHE MANIFEST

# Version 1.0
# この行はコメントです。マニフェストの更新は、このコメントを変更することで行います。

CACHE:
# キャッシュするファイルのリスト
/index.html
/styles.css
/scripts.js
/images/logo.png

NETWORK:
# ネットワークから常に取得するファイルのリスト
# これらのファイルはオフラインでは利用できません
/ajax/
https://api.example.com/

FALLBACK:
# オフライン時に代わりに使用するファイルのリスト
/ /offline.html


applicationCache.statusプロパティ

キャッシュの状況を取得するためのプロパティ

applicationCache.UNCHACHED(0)
リソースがキャッシュされてない

applicationCache.IDLE(1)
待機中

applicationCache.CHECKING(2)
チェック中

applicationCache.DONWLOADING(3)
ダウンロード中

applicationCache.UPDATEREADY(4)
キャッシュされたリソースの更新準備が完了した

applicationCache.OBSOLETE(5)
キャッシュが破棄された

applicationCache 関連イベント

checking
 更新の確認中。一連のイベント中で最初に発生する

error
 マニフェストファイルなどのダウンロードに失敗した時に発生する

noupdate
 マニフェストファイルが更新されていない時に発生する

downloading
 マニフェストファイルの更新を確認し、取得を開始した時に発生する

updateready
 リソースのダウンロードが完了した時に発生する

cached
 リソースのキャッシュが完了した時に発生する

obsolete
 マニフェストファイルが見つからなかったときに発生する


navigator.onLineプロパティ

オンライン状況を確認するためのプロパティ















オフラインアプリケーションAPI

オフラインアプリケーションのためのService Workersの例

self.addEventListener('install', (event) => {
    event.waitUntil(
        caches.open('v1').then((cache) => {
            return cache.addAll([
                '/',
                '/index.html',
                '/styles.css',
                '/script.js'
            ]);
        })
    );
});

self.addEventListener('fetch', (event) => {
    event.respondWith(
        caches.match(event.request).then((response) => {
            return response || fetch(event.request);
        })
    );
});
if ('serviceWorker' in navigator) {
    window.addEventListener('load', () => {
        navigator.serviceWorker.register('/service-worker.js').then((registration) => {
            console.log('ServiceWorker registration successful with scope: ', registration.scope);
        }, (error) => {
            console.log('ServiceWorker registration failed: ', error);
        });
    });
}



Page Visibility

webページが表示/非表示の状態になると、visibilitychangeイベントを発生させるAPI

・visibilitychangeイベントが発生するタイミングは、ブラウザを最小化、ブラウザのタブの切り替え

・Page Visibilityを使用して、ユーザがwebページを閲覧していないタイミングでは処理を停止することで、マシンリソースの節約ができる
・MediaElementと連携させて、ユーザがブラウザを非表示にしている間、ビデオ再生を停止できる

・visibilitychangeイベント発生時に処理を実行するには、
onvisibilitychangeイベントハンドラに処理を登録する

・visibilityStateプロパティを確認することで、
 表示状態か非表示状態か判定できる

・visibilityStateプロパティの値がhidden, つまり非表示になる場合は、
ブラウザを最小化する、ブラウザのタブを切り替えて他のページを閲覧している、など

visibilityStateプロパティが返す値

visible
 webページが表示されている状態
hidden
 非表示(ブラウザが最小化されているなど)の状態
prerender
 webページがレンダリング前(2版で廃止)
unloaded
 webページがメモリから解放されている(2版で廃止)




ページの可視性を監視する例

document.addEventListener('visibilitychange', () => {
    if (document.hidden) {
        console.log('Page is hidden');
    } else {
        console.log('Page is visible');
    }
});


PerformanceTimingオブジェクト

webページの取得からロード完了までのパフォーマンス情報を提供するもの

Perfomanceオブジェクトの各種プロパティにアクセスする
-> タイミングごとの詳細な時刻表示を取得する



Navigation Timing API

ページのナビゲーションに関するタイミング情報を取得する例

window.addEventListener('load', () => {
    const timing = window.performance.timing;
    const pageLoadTime = timing.loadEventEnd - timing.navigationStart;
    console.log(`Page load time: ${pageLoadTime} milliseconds`);
});









セキュリティモデル


オリジン

スキーム://ホスト名:ポート番号

同一オリジンの例

http://www.knowledgewing.com/kw/index.html
http://www.knowledgewing.com/kw/?q=flm


同一オリジンポリシー
webページから異なるオリジンのリソースにアクセスできないようにすること
クロスオリジンを出来ないようにする

クロスオリジンの例
http://www.aaaaa.com/  -> http://www.bbbb.com/

とアクセスすること


Originヘッダ

・リクエスト元のオリジンを表すリクエストヘッダ
・POSTリクエストやCORSリクエストの際に、ブラウザからwebサーバに送信される
・Referヘッダに似てるが、Originヘッダはオリジンのみを含む


CORSリクエスト(Cross-Origin Resource Sharing)

Access-Control-Allow-Originヘッダなどを使用して、現在のオリジンとは別のオリジンのリソースにアクセスする権限

つまり、別のオリジンのページにアクセスできるようにする


HTTP通信では、セキュリティの関係上、クロスオリジンリクエストは許可されていない
Access-Control-Allow-Originヘッダなどを使えば、アクセスできるようになる


主な、CORS関連のヘッダ

Access-Control-Request-Method
Access-Control-Request-Headers
Access-Control-Allow-Origin
Access-Control-Allow-Methods
Access-Control-Allow-Headers



Access-Control-Allow-Origin

・アクセスを許可するオリジンを指定するレスポンスヘッダ
・webサーバ側でアクセスを許可するオリジンを指定し、クライアントにレスポンスする
・許可されていないオリジンからリクエストがある場合、同一オリジンポリシー違反でアクセスを拒否する



プリフライトリクエスト

・メインとなるリクエストを開始する前に、OPTIONSリクエストメソッドを使用し、安全に通信できるか調査するリクエスト
・PUT, DELETEメソッドのみ発生する
・GETやPOSTの場合は、プリフライトリクエストは発生しない
・プリフライトリクエストを行えば、webサーバから対応するリクエストメソッドの一覧やヘッダ情報を取得できる
・HTTPS通信でも発生する


ブラウザのセキュリティモデル


JavaScriptのAPIには、セキュリティの観点からHTTPS通信以外で動作しないAPIがある。

Service Workers

webページとは別にブラウザのバックグラウンドで動作するJavaScript実行環境

HTTPS通信でしか動作しない

Geolocation API

HTTPS通信でしか動作しない

Secure Contexts / Mixed Content

Secure Contexts

・HTTPSなどの暗号化された通信を介して安全に提供されているコンテンツ(windowやworkerなど)

・webページ内の全ての通信をHTTPS通信などで暗号化しないとSecure Contextsできない
・HTTPS通信を実現するために、SSL/TLSによる暗号化が必要になる
・中間者攻撃を防ぐために使われる
 中間者攻撃とはなりすましのこと
・Geolocation APIやService WorkersなどはSecure Contextsでのみ使用可能

Secure Contextsとみなされる例)
・webページ内のiframe要素のsrc属性でHTTPS通信を行っている
・webページ内でXMLHttpRequestによるHTTPS通信を行っている


Mixed Content

・HTTPS通信でwebページを公開しても、webページ内で暗号化されていない通信(HTTP通信)を行っていたら、Mixed Contentとみなす
・Mixed Contentの場合、デベロッパーツールのコンソールには警告が表示される

Secure Contextsの場合のみ、localStorageに格納されている値にアクセスさせる場合

window.isSecureContextを使用して、JavaScriptでSecure Contextsか判断する

if (window.isSecureContext) {
    // Secure Contextsの場合のみ、localStorageを呼び出す
    var data = localStorage.getItem("Foo");
}





この記事が気に入ったらサポートをしてみませんか?