JavaScript
JavaScriptのすべての仕組み
JavaScript Primer(めちゃくちゃわかりやすい)
next/script には JavaScript の基本がつまっていた
JavaScript アニメーション仕組み
npm人気なパッケージを見つける
本当に必要なnpmパッケージを見つけるために知っておきたい5つのサイト
JavaScriptの時間
Date
がミリ秒のため * 1000
が必要
※UNIXタイムスタンプは10桁
// 13桁でミリ秒までやっている
new Date().getTime()
// 1668826244442
アロー関数と this
アロー関数は特別な関数ですが、一番の特徴は this
キーワードの扱い方。
アロー関数は this
をレキシカルに捉える、つまり this
はアロー関数が定義されたスコープの this
を指すようになります。
通常の関数宣言を使用すると、this
は呼び出し時のコンテキストを指します。したがって、オブジェクトのメソッドとして関数を呼び出すと、this
はそのオブジェクトを指します。
例
const obj = {
value: 'hello',
getValue: function() {
console.log(this.value);
},
getArrowValue: () => {
console.log(this.value); // ここでの `this` は `obj` を指していない
}
};
obj.getValue(); // "hello" と出力される
obj.getArrowValue(); // undefinedと出力される
この例でわかるように、アロー関数内の this
は obj
を指さない。そのため this.value
は undefined
となります。
あなたのケースで
アロー関数をメソッドとして使用すると、そのメソッド内の this
はそのメソッドが属するオブジェクトを指さなくなります。そのため、this
キーワードをメソッド内で使用する場合、通常の関数宣言を使用するのが一般的です。または、this
を変数にアサインしてからアロー関数を使用することもあります。
この概念はJavaScriptおよびTypeScriptの中心的な概念であり、this
の扱いはとくに初心者には混乱を招くことが多いです。このため、どのように機能するかを理解することは非常に重要です。
JavaScriptの実行環境
安心安全に利用できる理由は、サンドボックスで動作するため。 サンドボックス上で動作していると、アクセスできるファイルや実行できるプログラムが制限されてしまう。 その代わりに、その制限下では自由な利用が許可されています。 JavaScriptのサンドボックスによる代表的な制約のひとつに同一オリジンポリシー (same-origin policy) がある。
JSのスレッド
JSの同期処理&非同期処理はメインスレッドで実行される(UIスレッドとも呼ばれる)
同期処理はブラウザはしてほしくない
同期的にブロックする処理があると、ブラウザでは大きな問題となる。 JSは基本的にブラウザのメインスレッド(UIスレッドとも呼ばれる)で実行されるため。 メインスレッドは表示の更新といったUIに関する処理も行なっているためメインスレッドが他の処理で占有されると表示が更新されなくなりフリーズしたようになる。
非同期処理はメインスレッドで実行され る(つまり並行)
JSにおいて多くの非同期処理はメインスレッドで実行される(すべてではないが基本は) 非同期処理も同期処理の影響を受ける(どちらかが遅ければ引っ張られる)
またJSでは一部の例外を除き非同期処理が並行処理(concurrent)として実行される。 ※並行処理とは、処理を一定の単位ごとに分けて処理を切り替えながら実行すること。
このようにJSの非同期処理も基本的には1つのメインスレッドで処理されている。
これは setTimeout
のコールバックが外側のスコープデータへのアクセス制限がないことからも汲み取れる。
もし非同期処理が別スレッドで行われるならば、自由なデータへのアクセスは競合状態(レースコンディション)を引き起こしてしまう。
非同期の中にも別スレッドで実行できるのがある。
たとえばブラウザでは Web Worker
APIを使い、メインスレッド以外でJSを実行できる。
ただし、非同期処理の中にもメインスレッドとは別のスレッドで実行できるAPIが実行環境によっては存在します。 たとえばブラウザではWeb Worker APIを使い、メインスレッド以外でJavaScriptを実行できます。 このWeb Workerにおける非同期処理は並列処理(Parallel)です。 並列処理とは、排他的に複数の処理を同時に実行することです。 Web Workerではメインスレッドとは異なるWorkerスレッドで実行され るため、メインスレッドはWorkerスレッドの同期的にブロックする処理の影響を受けにくくなります。 ただし、Web Workerとメインスレッドでのデータのやり取りにはpostMessageというメソッドを利用する必要があります。 そのため、setTimeout関数のコールバック関数とは異なりデータへのアクセス方法にも制限がつきます。
非同期処理と例外処理
同期処理では try...catch
構文を使うことで同期的に発生した例外がキャッチできる。
※非同期処理では try...catch
構文を使っても非同期に発生した例外をキャッチできない(同期処理が終わった後に例外が発生するため)
そのため、setTimeout関数のコールバック関数における例外は、次のようにコールバック関数内で同期的なエラーとしてキャッチする必要があります。
// 非同期処理の外
setTimeout(() => {
// 非同期処理の中
try {
throw new Error("エラー");
} catch (error) {
console.log("エラーをキャッチできる");
}
}, 10);
console.log("この行は実行されます");
このようにコールバック関数内でエラーをキャッチできるが、非同期処理の外からは非同期処理の中で例外が発生したかがわからない。
非同期処理の外から例外が起きたことを知るためには、非同期処理の中で例外が発生したことを非同期処理の外へ伝える方法が必要です。
asyncでのエラーとは
await式の右辺のPromiseがRejectedとなった場合は、その場でエラーをthrowします。 またAsync Function内で発生した例外は自動的にキャッチされます。 そのためawait式でPromiseがRejectedとなった場合は、そのAsync FunctionがRejectedなPromiseを返すことになります。
つまり
await式でPromiseの状態を待機できるということは try...catch
構文でキャッチができる。
通常の非同期処理では完了する前に次の行が実行されてしまうためtry...catch構文ではエラーをキャッチできませんでした。
そのためPromiseではcatchメソッドを使ってPromise内で発生したエラーをキャッチしていました。
次のコードでは、await式で発生した例外をtry...catch構文でキャッチしています。 そのため、asyncMain関数はResolvedなPromiseを返し、catchメソッドのコールバック関数は呼び出されません。
async function asyncMain() {
// await式のエラーはtry...catchできる
try {
// `await`式で評価した右辺のPromiseがRejectedとなったため、例外がthrowされる
const value = await Promise.reject(new Error("エラーメッセージ"));
// await式で例外が発生したため、この行は実行されません
} catch (error) {
console.log(error.message); // => "エラーメッセージ"
}
}
// asyncMainはResolvedなPromiseを返す
asyncMain().catch(error => {
// すでにtry...catchされているため、この行は実行されません
});
SourceMapについて
JavaScriptのタイムゾーン
CommonJSとESModule
CommonJS : nodeのやつ require
まだECS(ESModule)でモジュールシステムが導入されていないときにnodeで実装したモジュールシステム CommonJSではブラウザ上だけでなく、サーバーサイドやクライアントでのCUI、GUIでJavaScriptを使う際の仕様を作成している。 単に仕様を作っているだけなので、ECMAScriptに組み込まれるとかがない限り、それがJavaScriptの標準になるというわけではない模様
ちなみに CommonJS で作成された仕様は複数のソフトウェアによって実装が行われることで勧告段階に移るみたいです。 CommonJS の仕様を実装しているソフトウェアの中にはあの有名な node.js があります。
ESM(ECMAScript) : importのやつ
実質のJSの仕様を策定するもの。 ECMAScript はブラウザ上での JavaScript の仕様と標準を作っている。
CommonJS と ES6の import/export で迷うなら
jsの演算子ドキュメント リファレンス
JS 配列メソッド一
async await
// axiosでjson取得
export const ApiGet_Simple = (async (url:string) => {
try {
// 指定URLにGET
const res = await axios.get<jsonType[]>(url);
// (↑のawaitがついていると関数が実行完了するまで↓を動作しない仕組み)
// 動作が完了して、リターンしてきたjsonを返す
return res;
} catch (err) {
// 途中でエラーが出たら強制でエラーをスロー
throw new Error(err.status);
}
});
Optional Chaining
Optional Chainingはundefinedもしくはnullな値のプロパティをランタイムで安全に参照できるようにするシンタックスです。
const a = obj?.foo;
// これと変わらない obj != null ? obj.foo : undefined
const foo: any = {};
foo.bar.baz;
// js: TypeError: Cannot read property 'baz' of undefined
foo.bar?.baz;
// js: undefined
Nullish Coalescing ??
Nullish Coalescingは値が undefined
もしくは null
のとき、フォールバックとして別の値を返せるようにするオペレーター
undefined ?? 'fallback';
// js: 'fallback'
null ?? 'fallback';
// js: 'fallback'
'hello' ?? 'fallback';
// js: 'hello'
これまで || を使用していた初期値代入のうち、0やfalseといったFalsyな値を正常値として扱いたいときにNullish Coalescingで置き換えられる。
0 || 'fallback';
// js: 'fallback'
0 ?? 'fallback';
// js: 0
false || 'fallback';
// js: 'fallback'
false ?? 'fallback';
// js: false
in 演算子
in演算子は、指定されたプロパティが指定されたオブジェクトにある場合trueを返す
const car = { make: 'Honda', model: 'Accord', year: 1998 };
console.log('make' in car);
// expected output: true
JavaScriptの配列のmapでasync/awaitを使う方法
Promise
Promiseの状態 上述したとおり、Promiseには処理に応じた「状態」があり、次の3つのうちの1つになる
pending: 初期状態、まだ処理が成功も失敗もしていない fullfilled: 処理が成功し、完了した状態 rejected: 処理が失敗した状態
Promise.all()
Promise.all()は
all()の引数の配列内のPromiseの状態がすべて fullfilled
になったら、all()自体も fullfilled
になる。
1つでも rejected
になると、all()も rejected
を返す。
非同期処理
非同期処理とは、ある関数が呼ばれた時に返り血として渡したい値を返すのではなく一度関数として終了し渡したい値を返せる状態になったら呼び出し元にその値を返すというもの。
非同期処理イメージ
イメージとして電子レンジを思い浮かべると良いでしょう. 電子レンジでおにぎりを温める時, 私たちはタイマーをセットしていったん待ちます. これが「関数として一度終了している状態」です. そして, 時間が経つとおにぎりが食べられる状態になります. これが「渡したい値を返せるよう状態になったらその値を返す」ということです.
jsの時間の求め方
jsではUNIXタイムスタンプに変更するのが一番良い
/**
* @desc 来月の初日のticket終了時間をsetする
* @example 来月の初日の 27:59:59 → 2021/10/01 03:59:59
* @return unix timestamp
*/
Date.formatYumegraTicketLastTime = (month: number = 1): number => {
const to = new Date();
to.setMonth(to.getMonth() + month); // 来月の現在時間
to.setDate(0); // 今月の末日
to.setHours(27);
to.setMinutes(59);
to.setSeconds(59);
return to.getTime();
};
/**
* @desc その月の最終日付を返す(デフォルトで今月)
* @param 1 2021/11/31 23:59:59 今月
* @param 0 2021/10/31 23:59:59 先月
*/
Date.formatTicketCountLastTime = (month: number = 1): number => {
const to = new Date();
to.setMonth(to.getMonth() + month); //
to.setDate(0); // 今月の末日
to.setHours(23);
to.setMinutes(59);
to.setSeconds(59);
return to.getTime();
};
分割代入
- 分割代入の時のデフォルト値が使われる基準
Falsyの時でもなく、undefinedの時のみ使われる。Nullishの時ではなくundefinedの時
const {a: {a1, a2}, b: {b1}} = {a: {a1: 1}, b: {}}
動的なプロパティ名
オブジェクトのプロパティ名は動的にできる。
const type = 'id';
const item = {
[type]: 'abcd01234';
};
console.log(item); // { id: 'abcd01234' }
console.log(item[type]); // 'abcd01234'
console.log(item['id']); // 'abcd01234'
console.log(item.id); // 'abcd01234'
配列をオブジェクトに変換する
const array = [1, 2, 3];
const object = { ...array };
console.log(object); // { 0: 1, 1: 2, 2: 3 }
最新のJS Tips
ESLintとPrettierを合わせる意味
ESLint単体コードフォーマットが可能だが、Prettierでは整形できないコードも整形するため よくある動機としてはESLintに静的検証を行わせ、Prettierはフォーマットを担う
- TypeScript対応
ESLintについて
pluginsとextendsの違い
plugins ルールセットを持つプラグインを指定する項目。 本来であればpluginsにプラグインを指定して、且つextendsにそのプラグインが持つルールを指定しないと検証時にルールが適用されないらしいが、prettierはなぜかpluginsに指定しただけでルールが適用されてる。謎。
基本的にはeslint-plugin-xxxというパッケージのxxxの部分をpluginsに記述してあげればいいらしい。
extends プラグインが提供するルールを指定する項目。 eslint-plugin-xxxというパッケージをpluginsで指定した場合は、extendsにxxx/yyyというふうにルールを指定してあげるらしい。
また、pluginsは使わずにeslint-config-zzzというパッケージをインストールし、extendsにzzzと指定してあげてもなんとかなるっぽい。
ESLint 設定ファイル読み込み
ESLintの設定はいくつかの形式で記述できるが、それぞれ読み込みに優先度がある。優先度は以下の通り。
.eslintrc.js .eslintrc.yaml .eslintrc.yml .eslintrc.json .eslintrc package.json
file
- 存在確認
JS(感嘆符) 2つ
if(!true){
alert("trueです。");
}else{
alert("falseです。");
コールバック関数
よく使われる解説
別の関数に呼び出してもらうための関数
タグ付きテンプレートリテラル
styled-componentsで使用されているやつ 参考URL