Open hysryt opened 2 years ago
ES2022で追加される予定の仕様。
class Human {
#age = 20;
}
#
で始まるインスタンスフィールドはプライベートになる。
重要な特徴として、プライベートフィールドはインスタンス内でもクラスごとに保持されるというものがある。
class Human {
#age = 20;
sayAge() {
console.log(this.#age); // Humanの#ageを指す
}
}
class Man extends Human {
#age = 30;
sayAge2() {
console.log(this.#age); // Man の#ageを指す
}
}
const man = new Man();
console.log(man.sayAge()); // 20
console.log(man.sayAge2()); // 30
上記のように、man
インスタンスの中には Human
の #age
と Man
の #age
が格納されており、それぞれは別物として扱われる。
基本的には別のインスタンスのプライベートフィールドにはアクセスできないが、同じクラスであれば別のインスタンスのプライベートフィールドを読み取ることができる。
in
#age in obj
で obj
が #age
というプライベートフィールドを持っているかどうかを判断できる。
この式を使えるのは #age
をもつクラスのメソッドのみ。(クラスメソッドでも使える?)
Human
クラス内で上記の式を使った場合、 #age
は Human
クラスの #age
という意味になる。
そのため obj
が Animal
クラスで、このクラスも #age
を持っていたとしても、上記の式は false
となる。(obj
が持つのは Animal
クラスの #age
であって、Human
クラスの #age
ではないため)
この式を使うと、「そのオブジェクトがHumanクラスのインスタンスかどうか」を確かめることもできる。
インスタンスかどうかを確かめるには obj instanceof Human
も使用できるが、こちらはプロトタイプの情報を見ているだけなので、Human
をインスタンス化したものでなくても上記の式が true
となるようなオブジェクトを作成できてしまう。
JavaScriptでは先にスコープ内の定義をすべて読み込む。 そのため定義より前に関数の呼び出しを記述していても問題なく動作する。
var
による定義は、初期値が与えられていない場合は巻き上げ時に undefined
が代入される。
let
や const
による定義は、初期値が与えられていない場合は巻き上げ時には何も代入されない。
DOM をカプセル化する。 Shadow DOM の内部は開発者ツールからも見ることができない。
attachShadow()
element.attachShadow(shadowRootInit)
element
を Shadow Host として Shadow DOM を追加する。
Shadow Host から Shadow root を取得できる。
element.shadowRoot
Shadow DOM は通常のDOM APIで操作できる。
const host = document.querySelector('#host');
const shadow = host.attachShadow({mode: 'open'});
const child = document.createElement('div');
child.textContent = 'hello';
shadow.appendChild(child);
参考 https://developer.mozilla.org/ja/docs/Web/Web_Components/Using_shadow_DOM
ECMAScript5から追加された。 モジュールは自動的にstrictモードとなる。
strictモードには以下のような特徴がある。
strictモードを有効にするにはファイルの先頭に'use strict;'
と記述する。
エクスポートは named export か default export のどちらかの方法で行う。 default export の場合は1つのモジュールにつき1つのエクスポートしかできない。 named export は1つのモジュールにつき0以上のエクスポートができる。
以下は一例
export const x = 10;
export function test() {...}
export class Test {...}
// まとめてexport
export { name1, name2, name3 };
// 名前を変えてエクスポートすることも可能
export { name1 as alias };
変数、関数、クラスは宣言の直前に export
をつければ named export になる。
named export は
import { name } from './module.js';
という構文でインポートする。
以下は一例
export default function() {...}
export default class {...}
// 名前付きの default export もある
export default class Test {...}
// default という名前でエクスポートすると default export になる
export { name1 as default };
default export は
import name from './module.js';
という構文でインポートする。
この時 name
は自由に決められるが、基本的にはファイル名と同名にすることが多い。
ジェネレータ関数は Generator
オブジェクトを返す。
帰ってきた Generator
オブジェクトの next()
を呼び出すことで次の yield
までを実行できる。
function* testGen(i) {
yield i;
yield i + 1;
yield i + 2;
}
const gen = testGen(1);
console.log(gen.next().value); // 1
console.log(gen.next().value); // 2
console.log(gen.next().value); // 3
next()
は value
プロパティと done
プロパティを持つオブジェクトを返す。
next()
を呼び出したときに次の yield
がない場合は done
が true
になる。
Generator
オブジェクトは iterable プロトコルと iiterator プロトコルに準拠している。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Iteration_protocols
イベントループ
https://ja.javascript.info/event-loop
setTimeoutで設定した関数は macrotask キューに追加される。 queueMicrotaskやPromiseハンドリングは microtask キューに追加される。 (macrotaskはV8の用語らしい。仕様上では「タスクキュー」?)
setTimeout
仕組みはよくわからないが指定したコールバック関数は指定した時間の後 macrotask キューに追加される。
Promise
仕組みはよくわからないがPromiseがresolveまたはrejectされると登録されていたコールバックが microtask キューに追加される。
async/await
Promiseのシンタックスシュガー。 以下の2つは同等。つまりawait以降の処理はPromiseがresolveされると microtask キューに追加される。