hysryt / wiki

https://hysryt.github.io/wiki/
0 stars 0 forks source link

JavaScript #186

Open hysryt opened 2 years ago

hysryt commented 2 years ago

イベントループ

https://ja.javascript.info/event-loop

  1. macrotask キューにある最も古いタスクを取り出して実行
  2. すべての microtask を実行
  3. 変更がある場合はレンダリング
  4. macrotask キューが空であれば、macrotask が現れるまで待つ
  5. ステップ1 戻る

setTimeoutで設定した関数は macrotask キューに追加される。 queueMicrotaskやPromiseハンドリングは microtask キューに追加される。 (macrotaskはV8の用語らしい。仕様上では「タスクキュー」?)

setTimeout

仕組みはよくわからないが指定したコールバック関数は指定した時間の後 macrotask キューに追加される。

Promise

仕組みはよくわからないがPromiseがresolveまたはrejectされると登録されていたコールバックが microtask キューに追加される。

async/await

Promiseのシンタックスシュガー。 以下の2つは同等。つまりawait以降の処理はPromiseがresolveされると microtask キューに追加される。

const data = await fetch();
console.log(data);
fetch().then(data => {
  console.log(data);
});
hysryt commented 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#ageMan#age が格納されており、それぞれは別物として扱われる。

基本的には別のインスタンスのプライベートフィールドにはアクセスできないが、同じクラスであれば別のインスタンスのプライベートフィールドを読み取ることができる。

in

#age in objobj#age というプライベートフィールドを持っているかどうかを判断できる。 この式を使えるのは #age をもつクラスのメソッドのみ。(クラスメソッドでも使える?)

Human クラス内で上記の式を使った場合、 #ageHuman クラスの #age という意味になる。 そのため objAnimal クラスで、このクラスも #age を持っていたとしても、上記の式は false となる。(obj が持つのは Animal クラスの #age であって、Human クラスの #age ではないため)

この式を使うと、「そのオブジェクトがHumanクラスのインスタンスかどうか」を確かめることもできる。 インスタンスかどうかを確かめるには obj instanceof Human も使用できるが、こちらはプロトタイプの情報を見ているだけなので、Human をインスタンス化したものでなくても上記の式が true となるようなオブジェクトを作成できてしまう。

hysryt commented 2 years ago

Hoisting(ホイスティング、巻き上げ)

JavaScriptでは先にスコープ内の定義をすべて読み込む。 そのため定義より前に関数の呼び出しを記述していても問題なく動作する。

var による定義は、初期値が与えられていない場合は巻き上げ時に undefined が代入される。 letconst による定義は、初期値が与えられていない場合は巻き上げ時には何も代入されない。

hysryt commented 2 years ago

Shadow DOM

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

hysryt commented 2 years ago

strictモード

ECMAScript5から追加された。 モジュールは自動的にstrictモードとなる。

strictモードには以下のような特徴がある。

strictモードを有効にするにはファイルの先頭に'use strict;' と記述する。

hysryt commented 2 years ago

モジュールのエクスポート

エクスポートは named export か default export のどちらかの方法で行う。 default export の場合は1つのモジュールにつき1つのエクスポートしかできない。 named export は1つのモジュールにつき0以上のエクスポートができる。

named export

以下は一例

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';

という構文でインポートする。

default export

以下は一例

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 は自由に決められるが、基本的にはファイル名と同名にすることが多い。

hysryt commented 2 years ago

ジェネレータ関数

ジェネレータ - Wikipedia

ジェネレータ関数は 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 がない場合は donetrue になる。

Generator オブジェクトは iterable プロトコルと iiterator プロトコルに準拠している。 https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Iteration_protocols