t_hazawaの日記

株式投資とWebエンジニアリングのブログです。株式投資の目次は→です。 https://t-hazawa.hatenablog.com/entry/2021/02/12/220933

Jest(JavaScriptテストライブラリー)をやってみた

前回: TypeScriptの組み込み方を学んだ(webpackで ts-loader), webpack plugin 色々 - t_hazawaの日記

経緯

  • あるプロジェクトのJSをTypeScriptにしたい
  • 前回までで、TypeSctipt自体は結構学んだ
  • テストがまだ
  • Jestやってみた

やったこと

  • TypeScript の単体テストで Jest 使おう - Qiita
  • jest も npm で入れるものなのね
  • この Qiitaのことを自分でもやってみた
  • Windows10 VSCode でやってる
  • npm init -y
    npx tsc -init          
    npm install typescript せよと言われたのでした npx tsc -init
  • npm install ts-node したら npm t (テスト実行コマンド)通った
  • テストもテスト対象も src/ に入れたらできた
  • やりきった

  • 実際に、プロダクトのJSをTSにすべく、計画を立てる (どこをやってみるつもりとか)

TypeScriptの組み込み方を学んだ(webpackで ts-loader), webpack plugin 色々

前回: サバイバルTypeScriptを読んだ - t_hazawaの日記

やりたいこと・概要

  • TypeScriptになってないが、そこそこJSがモダンなプロダクトがある
  • TypeScript を導入したい
  • 前回、TypeScript 自体を勉強した
  • TypeScript をどう導入するかしらべたぞ
    • 大体 webpack で ts-loader

時間まとめ

今回

  • 2/28-3/7 に組み込み方まなんでいた
  • (3/9-3/31 まで評価資料作ってた)
    • 今度から、月の最後の2日間を毎月当てようと思う(各月2時間弱)
  • 4/1-4/23に続きを学んだ
  • 4/24-4/27 にこのブログを書いていたが、その後、4月分の評価資料を作り始めたら、ストップウォッチを使わず、1日にちょこっとずつしか進めなかったので、12日間も評価資料(4月分)を作っていた
    • モチベが低い作業はストップウォッチを使わないと本当にほんの少ししかしない(学び)

つまり

  • TSの組み込み方の勉強には1ヶ月かかった

勉強したこと (まとめ)

  • webpack.js の module: { rules: [ で test で .ts だけを ts-loader に流し込むことができるのだ
    • 流し込んだやつを他のJSと一緒にバンドればいいのだ
  • 我々の プロダクトは yarn で package.json のことを実行し、そこに "scripts": { "build:prod": "webpack --config webpack.prod.js とかかれてて、webpack を実行してる
  • package.json のことも調べた

勉強したこと (詳細)

Jest 編

まだ謎なこと

  • Jestの運用への組み込み方

次回

  • Jest を今のプロダクトのどこに組み込めるか考える
    • Jenkins?
  • どのように導入しようと考えてるか共有する
  • 一箇所で導入してみる

サバイバルTypeScriptを読んだ

経緯

読み終わった感想

読んで学ぶ部分がボリューミーでした (そこだけで18時間)
(今日ブログ(5万字メモがある)にします)『サバイバルTypeScript』はJS自体とTS自体を全体的に網羅していてよかったです。
JSの説明については、ところどころ簡潔すぎて、「これだけの説明ではわからなさそう」という感じのところがあったので、そこだけ『JavaScript初心者から中級者になろう』で詳しく知るといいかも、…と思いました。『JavaScript初心者から中級者になろう』は懇切丁寧で著者のuhyoさんの話も面白いのですが、何分量が多いですね。

かかった時間

  • 2022/1/29 - 2/22

はじめにから

https://typescriptbook.jp/

3000時

最短を目指してるらしい

> rubypythonなどの動的型付け言語を主に扱ってきており、型をそこまで意識してこなかったので、型システムについて学ぶ必要性を感じている。 

あらまし

400時

特徴

1800時

> TypeScriptはMicrosoftにより2012年10月1日に発表されました。

コンパイルがいります

> 何よりたのしい

たのしみ

型推論のおかげでタイプ量がだいぶ減るらしい

> これまでjavascriptに型がないことにより悩まされてきた"実行してみないとわからない"恐怖から解消され、プログラミングを楽しくできます


JavaScriptはTypeScriptの一部
500時

誕生の背景

> 代わりに、大規模開発の一部はtypescriptが引き受けることになったのです


今日は補助的な道具の上まで

2022/01/29 14:20 今日はおわり
  13:15に始めたので確かに一時間くらい
、

続き 2022/01/30 11:30

6300じ


> 1997年に、Microsoftが企業向けウェブメーラーとして、Outlook Web Access 2000を市場投入しましたが、これはJavaScript製のウェブアプリケーションでした。現代の我々からすると意外かもしれませんが、この時代のJavaScriptはまだサーバーと通信することができませんでした。そこで、Microsoftはこのアプリのために、後のXMLHttpRequest(XHR)となるXMLHTTPという機能をInternet Explorerに追加したりもしました

> google mapの成功を目にした開発者は、ブラウザさえあれば他に何もインストールする必要がないアプリケーションをユーザーに提供できるウェブアプリケーションにより一層の魅力を感じるようになり

むしろ、なぜネイティブアプリはあんなにインストールに時間がかかるのだろう 2022/01/30 11:42

> 2005年には、javascriptアプリケーションフレームワークの先駆けであるprototype.jsがリリースされました。翌年にはjqueryがリリースされ、その後しばらくして、2009年にangularjs、2010年にbackbone.js

> 2009年に発表されたcoffeescriptです。coffeescriptrubyのような簡潔な文法でコーディングできることが魅力の言語で、サーバーサイドフレームワークruby on railsにもフロントエンド開発用言語として正式採用されました。coffeescriptにはclass構文があり、

> 2012年に発表されたのがtypescriptです。

> 当時、人気を博していたcoffeescriptjavascriptの文法とはドラスティックに異なる独自路線を打ち出したのに対し、typescriptはjavascriptの文法を拡張するに留める「javascriptのスーパーセット言語」としての戦略を採用しました


> typescriptが誕生当初に掲げていた3大特徴のうち、モジュール性はjavascriptの仕様にも盛り込まれ、その部分ではtypescriptは優位性を失いました。 

スーパーセット もじゅーる 型

エコシステム

2000時

2022/01/30 12:05

> 静的型検査での同様な立ち位置の技術としてflowが挙げられます

> flowには独自の言語がなく、あくまでjavascriptにコメントのような型アノテーションを追加しただけになっています

> これは不具合が含まれた製品がリリースされることが少なくなるということを意味します。。。これが型指定が多少面倒でもtypescriptやflowを導入する理由の一部となっています。 

> トランスパイラはtypescriptの他に、coffeescriptdartがあります

> トランスパイラの一種にbabelというツールがありま す

モジュールバンドラのwebpack, parcel

> タスクランナーは、ある決められた処理を実行しやすい形にまとめて、実行の順序などを意識せずに実行できるようにするツールです。gulpやgruntなど


> パッケージマネージャー npmや、npmを拡張したyarnが使われています。

> コードフォーマッタ よく使われるのが、Prettier(プリティア)と、ESLint(イーエスリント) Prettierはコード整形を主目的としています。一方ESLintはコードの間違いなども指摘してくれます。
 
2022/01/30 12:33 よみおわ 


なぜ使うべきか

2022/02/01 0:38 https://typescriptbook.jp/overview/why-you-should-use-typescript

4000時 (1200時引くといい全体から)

> airbnbによると、typescriptを使っていたらairbnbの38%ものバグを未然に防げたと見る分析を発表しています。 


> 静的チェックがあるおかげで、typescriptで検出できる類のバグはテスト工程から省略できるのは確かです

> typescriptの場合はひとまずjavascriptとして書き始め、少しずつtypescriptを学んでいき、徐々にtypescriptの恩恵を最大化するようにコードを手直ししていくといったアプローチが可能です

>  typescriptにはjavascriptにはない数多くの機能がありますが、どれも選択的に導入していくことができます。 


過去のesにもトランスパイルできるし、ESNextもどんどん取り入れてるらしいTS

新しいAPIは過去のesバージョンではつかえないとのこと

> もし、古い環境で新しいAPIを使う必要がある場合は、core-jsなどのポリフィルを併用することで解決することができます。 


プログラム言語人気ランキング9位
https://insights.stackoverflow.com/survey/2020#most-popular-technologies

PHPのひとつ下

静的型付け

2400時

> 静的型付け言語は「コンパイル時」に型が定まる。 

静的型付け言語にはコンパイルがあるんだね

> おかしな代入を早期発見できるというのが、typescriptを始めとした静的型付け言語の大きな利点になるわけです

めったに通らないパスでも確実に検出できてすごい 2022/02/01  1:14

> 動的型付け言語では書く必要がなかった型注釈を、typescriptでは基本的には変数ごとに書いていくことになります 

過去には静的→動的→静的という変遷があった

ECMAScript

2022/02/01  1:18

4200時

まぁ今日はここまで読めばいいかな

> netscape社は、javascriptを標準化するために、国際規格策定団体ecmaインターナショナルに依頼します。 javascriptが商標というのも一因だと考えられています javascriptは当時sunが所有する商標でした。その後、権利はoracleに引き継がれます。


> ecmascriptの規格番号はecma-262です。他にもjson(ecma-404)やc#(ecma-334)などがあります

stage3 になったあとにやっぱやめた、にはならないのかな?

> ecmascriptが決めるクライアントサイドjavascriptの仕様は部分的です

> JavaScriptのうちブラウザ仕様に関する部分は、HTML Living Standardが決めています。ブラウザでJavaScriptを使うと、触れることになるのがwindowオブジェクトやHTMLDivElement、ローカルストレージなどのAPIです。これらはHTML Living Standardと呼ばれる規格が定めています。この規格はEcmaインターナショナルとは異なる標準化団体WHATWGが策定しています。

> 「javascript」と一言で言っても、複数の規格で構成されているわけです

> 主要なブラウザの内部を分解すると、レンダリングエンジンやjavascriptエンジンと呼ばれる部品の単位があります

> JavaScriptエンジンには、主要なものでV8、SpiderMonkeyJavaScriptCoreがあります。

> 有名なレンダリングエンジンは、Blink、GeckoWebKitがあります

> Google ChromeはBlinkを、SafariWebKitを組み込んでいます。

> OperaレンダリングエンジンもPrestoでしたが、Blinkに変更した経緯があります。

> 同じブラウザブランドでも、iOS版のブラウザのレンダリングエンジンはWebKitです。たとえば、Google ChromeはBlinkを採用していますが、iOS版のGoogle ChromeレンダリングエンジンはWebKitです。これは、iOSレンダリングエンジンにWebKitだけが独占的に利用を許されているためです。


Firefox-Gecko-SpiderMonkey


いかにもapple製なJavaScriptCore

やはりJSはLinuxほどは面白くないのでは? 2022/02/01  1:44
 やっぱり結局はプレゼンテーションのところだけ感がある

ヨミオワ 2022/02/01  1:48

射程

2022/02/01 22:12

4000時

> typescriptを学んだらどのようなソフトウェアを作れるのか

ついさっき思ったことを説明し始めててすごい

tsはもちろん node.jsでも使えるよ

> バックエンド言語はjavarubyphpなどの多数の競合があるものの、typescriptもサーバーサイドプログラミングのひとつの選択肢になります。

> 両方でtypescriptを採用するメリット

> プロジェクトで扱う言語が1つでよい

バックエンドに向いてるのかな?


> モジュールを共有できる テストが倍にならない

フロントとバックでモジュールはどのくらい共通するのかな

> その言語のエコシステムや実務上のベストプラクティス、言語の細かい癖や陥りがちな罠などまで、しっかり理解した実践レベルに到達しようとなると、多くの学習時間を要します

> デスクトップアプリケーション。。windowsmacoslinux向けにデスクトップアプリケーションを作る場合もtypescriptが使えます。デスクトップアプリケーションをjavascript、html、cssの技術スタックで開発できるelectronを用います。 

> electron+typescript製の著名なアプリとしては、slackやmicrosoft社のvs codeがあります

なるほど

> cliアプリケーション。。コマンドラインツールの開発もtypescriptで行えます。サーバーサイドjavascript実行環境のnode.jsとtypescriptを組み合わせて開発します。

> CLIアプリケーションフレームワークには、Heroku製のoclifなどがあります Google製のzxを用いると、シェルスクリプトの代わりにTypeScriptを使うのもしやすくなります。

なんでもTypeScript

> Next.jsと親和性の高いVercelのServerless Functions、静的サイトホスティングで有名なNetlifyのNetlify Functions、世界90カ国194の都市にエッジを持つCDN CloudflareのCloudflare Workers


> typescriptでもiacを行えます。awsのインフラ構成を自動化するツールにaws cdk(cloud development kit)があります。これはtypescriptをサポートしています

たしかに

> AWSGoogle Platformなど複数のクラウドベンダーに対応したインフラ構成ツールとして、Pulumiもあります

> TerraformはHCLと呼ばれる独自言語で記述するのに対し、PulumiはTypeScriptなので、TypeScriptプログラマーにとって手が届きやすいツールです。


> google spreadsheetなどには、javascriptで機能を拡張する仕組みが備わっています。それをgoogle apps scriptと呼びます

自動化とかできるらしい

> typescriptで書いたコードはjavascriptコンパイルすれば、google apps scriptで利用できます

> ブラウザ拡張はjavascriptで書くことができます。typescriptで書いたコードもjavascriptコンパイルすることで、ブラウザ拡張として動かせます

いろんなところに使える JavaScript


> TensorFlow.jsはGoogleが開発した機械学習ライブラリです。Brain.jsはニューラルネットワークのライブラリです。 

> WebAssembly(WSM)はブラウザで動くアセンブリー言語です。WSMはJavaScriptよりも高速な処理が必要とされるところで用いられます。WSMのプログラムはC言語C++、Rustといったシステム言語で開発されることが多いですが、TypeScriptでWSMを開発できるようにする試みも出てきています。その筆頭がAssemblyScriptです。


2022/02/01 23:09


> Javaのキャストみたいなのはないよasは違うよ。instanceof Interfaceはできないよ。

作って学ぶ編

一通り React, Next.js, Jest(テスト) Prettier(整形), eslint(リンター)できるといいかも

eslintって小文字なんだ全部

開発環境

2000文字
一旦、今日は読むだけ読んで、明日やってみよう


> ブラウザはJavaScriptからHTMLを操作する必要があるのでDOM APIがありますが、Node.jsにはありません。代わりにNode.jsには、サーバーサイドのさまざまなリソースを制御する必要があるので、ファイルシステムにアクセスするAPIやHTTPサーバーを建てるためのAPI、プロセスを起動したり終了したりするAPIなどがあります。

なるほど。結構別物なのでは?


> Node.jsは、JavaScriptをサーバーサイドで動かすことを目的に開発されたソフトウェア

なんでもJavaScript の一環なのだ


Linux にも brew があるらしい

簡単な関数を作ろう編

2000時 今日はここまで読もう
 明日やってみよう


> コンパイラが指摘する問題点をすべて解消する作業のことを「コンパイルを通す」といいます。

懐かしい作業なのだ VC++

よみおわ 2022/02/02  0:27


●では実践しよう 2022/02/02 22:04

まずbrewを入れましょう

https://tech-blog.cloud-config.jp/2019-07-19-homebrew-on-wsl/

Homebrew
ホームディレクトリにパッケージをインストールできる(sudo不要)

> 使用しているディストリビューションでパッケージ化されていないソフトウェアもインストール可能


sudo apt update&&sudo apt upgrade

したが、いま 45分経過して snapd 212 

43分で 213くらいのパッケージをDLしたようだ

2022/02/02 23:03 58 分 apt upgrade がおわった


2/03 23:10くらい
もういっかい sudo apt update && sudo apt upgrade してみよう

チェックに割と時間がかかるね

いや、 12個本当に更新があったようだな…
1分くらいでおわった

slはいった 2022/02/03 23:46


●サバイバルTypeScriptにもどる 2022/02/03 23:48

https://typescriptbook.jp/tutorials/setup

brew install node@16

に10分はかかってる 2022/02/03 23:57
12分くらいでおわった

なんか入らなかったみたいなので
sudo apt install nodejs

してる

satoshi_takami@sa-takami-dl:~$ node -v
v10.19.0

めちゃふるかった

再度
brew install node@16

2022/02/04  0:04

echo 'export PATH="/home/linuxbrew/.linuxbrew/opt/node@16/bin:$PATH"' >> ~/.profile

して wsl立ち上げ直したら 16.13.2になった

tsc -v できた
2022/02/04  0:07

多分環境つくりできた 2022/02/04  0:07

2022/02/05 0:10 今日の実践開始

Reactでいいねボタンを作ろう

突然React

2022/02/05  0:19

まず読むか

> reactはfacebook社が開発したuiを作るためのパッケージ

Meta

> uiが複雑になるとreactなしではコードの記述量が増大したり、可読性が悪くなったりと難易度が上がります

> なんといっても、uiが今どのような状態なのかを管理するのは、プログラマが把握しきれない複雑さになることがあります

Reactはパッケージ

React の必要性わかった


> Reactでは 見てのとおり、どのように表示するかの部分はなく、「このような表示になってほしい」という目標だけが書かれています。

宣言的なコードつよい(命令は大変)

> ページもコンポーネント

> コンポーネントベースのメリットは、同じコンポーネントを再利用できる点です オープンソースコンポーネントも数多く公開されています

yarn 一瞬ではいった
2022/02/05  0:40


npxコマンド…? 2022/02/05  0:40

https://zenn.dev/ryuu/articles/what-npxcommand


> npxコマンドを使うことでインストールされていないコマンドであっても自動的に探してインストール、実行まで行ってくれます。

実行したあとはパッケージの除去まで行ってくれるため、環境が汚れる心配はないそうです。 インストールするまでも無いけど手軽に試したい、環境を汚したくないそんなニーズに

なるほど


npx create-react-app like-button --template typescript

3分くらいかかったけど


yarn start

react が ローカルサーバを用意してるのかな


> このHTMLに見える部分はJSXと言われるものです。JSXはJavaScriptを拡張した言語で、JavaScriptの中にXMLを直接書けるようにしたものです。

> jsxを戻り値にする関数をreact用語で「関数コンポーネント」と言います。 画面の部品をコンポーネントにしておくと、再利用できたり変更が一箇所で済んだりと、開発や保守がしやすくなります。


 今回作るボタンは次の図のようなシンプルなものです。 まで
2022/02/05  1:08


2022/02/07  0:43
機能はお腹がいたかったので休み

なんと.tsxの最後にcssをかける
駆けなかった App.cssだった

    cursor: pointer;

で手のマークになる

よく見る useState 関数

> setCountにはcountの値を変更する関数が代入されます。

> 次に、span要素をクリックしたときに、countの値を増加するhandleClick関数を実装します。

むずかしい

こーどよんだらよくわかった

まぁわかったかも 2022/02/07  1:00

17分しかやってないのでもう少ししよう

Next.js を調べるだけしようかな


https://qiita.com/Yuki_Oshima/items/5c0dfd8f7af8fb76af8f

語気がつよい 2022/02/07  1:02

けどしっかり書かれてそう


> Next.jsはモダンかつ強力なフロントエンドフレームワーク

React との関係はなんなのかな?

Reactの上にさらに載ってる感じみたいだね

> Next.jsはサーバーサイドレンダリング(SSR)やファイルベースルーティングなど多くの機能をゼロコンフィグで提供してくれます

> 開発会社Vercelが同名のプラットフォームVercelを展開しており、デプロイ/ビルド/配信までを一気通貫に提供

> Reactをベースにしている以上、Next.jsを使うべきかの判断はReactとの比較がポイント

Reactを強化したようなものなのかな? 2022/02/07  1:06

こういう5つの観点というか考慮ポイントがあるのね
 何を採用するか

> next.jsはアプリケーションを事前にページ単位でレンダリングします。クライアントからのリクエスト時にレンダリングするのがssr(server side rendering)と呼ばれる機能です。またビルド時にレンダリングする機能もあり、ssg(static site generation)と呼ばれます。 

サーバで処理するのね Next.js は、で、Reactに近いと
 Reactは クライアントでうごく

> またurlごとに個別のhtmlが生成されるのでseoに有利です。

HTMLがあると安心(?)

> 実用上リクエスト時までページの(静的な)内容が確定しないことはまれです

ログイン部分はJSでつくろうね

30分したのでおわり 2022/02/07  1:13

さて、具体的にssr/ssgを同実装するのかを から

> getStaticProps(SSG) を exportするだけ

> getServerSideProps(SSR)


getStaticProps() を実装して export async する

props: {
}
の中にあるのを function Blog  が処理するっぽい


☆ Next.js の方が SSG だからナウいし、早くてSEO的によさそう!
 つい今日、AmazonSSRして撃はやって記事をみたし
 SPAは表示までおそそう
    (謎のスプラッシュ挟むサイト多いし)

Next.js はルーティングがファイルのあり方に対応してて楽ちんらしい

> _app.tsxや_document.tsxは特殊なファイルで、URLには紐づけられません。これらはアプリケーションのエントリーポイントとしてReactのContext Providerを記述したり、HTMLのヘッダーを記述するために使います。

なるほど

> pages/post/[pid]/[comment].jsに対して/post/abc/a-commentというURLでアクセスすると

{ "pid": "abc", "comment": "a-comment" }

> next.jsの開発サーバはソースコードの変更を検知して、stateを保持したまま変更があった個所だけを更新してくれます。これにより、開発体験が大幅に向上します。例えば、フォームに入力した内容を保持したままタイトルのfont-sizeを変更することなどができます

うむう

> Next.jsでコンポーネントを書く際は常に関数コンポーネントに名前を付けてデフォルトエクスポートするようにしましょう。

> Next.js 10.0.0から専用の画像コンポーネントが追加され、配置されるサイズに応じて元画像をトリミングして配信してくれるようになりました。必要なサイズのデータだけをダウンロードするので画像の表示を大幅に高速化できます 

> レスポンス表示で幅が小さくなった場合も自動でそのサイズにトリミングした画像を生成してくれます。

すごそう


> 手書きでwebpackの設定を追加していくとしてもwebpackの設定ファイルを直接書き換えるよりはるかに楽です  Reactで細かいwebpackの設定をする際にnpm ejectしてwebpack.config.jsを編集することになりますが、かなり難しい作業です。


> 動的インポートしたコンポーネントはクライアントサイドでレンダリングされるため、実質的にReactと同じように処理される


ページ全体を SSGで作るには Next.js はいいんだろうけど、部分的な置き換えには使えなさそうな気がしてきた
 (React はどうだろう??)


>     Next.jsサーバへリバースプロキシ(next start)
    完全な静的リソースを生成してwebサーバから配信(next export)


> SSRを全く使わないならnext exportコマンドでReactと同じように静的リソースを生成することもできます。あとはそれをwebサーバに返してもらうだけです 

2020年12月のQiita

ヨミオワ 2022/02/07 18:45

きりいいのでおわろうかな

ーーー 2022/02/08 19:09 サバイバルTypeScriptに戻る

https://typescriptbook.jp/tutorials/jest Jest…は会社のプロダクトでやってる気がするからいいかな

Prettier 編 2022/02/08 19:10

https://typescriptbook.jp/tutorials/prettier

これはやりたいなぁ VSCodehttps://www.digitalocean.com/community/tutorials/how-to-format-code-with-prettier-in-visual-studio-code-ja

ググって一番上にでてきた


4ふんやった あと26ふん



VSCodeのPrettier は 1850万インストール


普通にフォーマットできた 2022/02/08 21:11


jsにもcssにもつかえるよ


.prettierrc.yml とかをつくろうね

やりきった 2022/02/08 21:16

次が何かみるだけしようかな

●eslintへん2022/02/08 21:17

https://www.google.com/maps/@34.6827335,135.188615,926m/data=!3m1!1e3?hl=ja
eslint prettier 違い 2022/02/08 21:17

https://qiita.com/soarflat/items/06377f3b96964964a65d
これを読もうかな 2022/02/08 21:18

まぁ、おわり

2022/02/09 22:06 よみはじめ

> eslint --fixでコード整形ができる
がraibaる


> 何故eslintだけではなくprettierも利用するのか

> eslint自体の説明は記載しておりません

むふう

> 読み方はプリティア

基本、フロントエンドだけに対応なプリティア

> npm install prettier@2.3.0 --save-dev

開発環境で使いたいものだもんね

> ファイルを上書きするために--writeオプションをつける。

prettier app.js --write

> eslintでもeslint --fixでコード整形ができるが、prettierの方がコード整形が優れている

> eslintと比べて手軽で確実に整形できる。。eslintでは整形できないコードを整形できる。。以下のような一行の文字数が長いコードはeslintでエラーが出力されるが、整形はされない。

つよい

> 上記のような整形をしてくれれば、複数のメンバーがエラーに対する独自の修正を適用し、更新するたびに差分が出てしまうような事態を防ぐことができる。


> eslint --fixは設定に該当したエラーのみを整形する。そのため、設定次第ではコードを整形しきれない。Prettier はデフォルトのスタイル(整形ルール)が存在する

ゼロコンフィグ


> 
    eslint(ESLint 本体)
    eslint-config-prettier(ESLint のフォーマット関連のルールを全て無効にする、要は Prettier が整形した箇所に関してエラーを出さなくなる)


http://tempest.blog.jp/archives/50414936.html
rc は run command らしい


package.json は scripts フィールドに、 実行コマンドをカケるんだね

> gitにはコミット前に指定のスクリプトを実行できるpre-commitフックと言う仕組みがある



> npm install husky@6.0.0 lint-staged@11.0.0 --save-dev
> 
    husky(Git のコミット時やプッシュ時に指定したコマンドを実行できる)
    lint-staged(Git のステージングに追加されたファイルにのみに ESLint などのリントを実行できる)


> npm set-script prepare "husky install"

package.json の "scripts" フィールドに "prepare" を追加するコマンド

> prepareはnpm installなどを実行時に自動で実行される。

読み終 21分かかった もうちょっとしよう 2022/02/09 22:28


eslint typescript vscode で検索


一番上の https://qiita.com/yuma-ito-bd/items/cca7490fd7e300bbf169

をやってみよう

2020/8/30

あんまりVSCode のことは載ってないかも?

VSCode の ESLint も 1850万インストール
  Prettier とかなり同じ

自動でならないが?

30分たったので、明日はこれが自動で整形されるようにしよう2022/02/09 22:36

2022/02/12  0:19 機能は会議がおおかったのでスキップなのだった

ESLint と Prettier を同時に format on save したいが動いてないだった

あのqiitaではうまくできないので、他の情報源を使うことにする

vscode eslint 動かない で検索 2022/02/12  0:26

https://note.kiriukun.com/entry/20190817-eslint-not-working-in-vscode
 むずかしい

https://iwb.jp/vscode-editor-eslint-error-reasons/
なるほど

https://qiita.com/genbu-jp/items/a48bcb9df209b71c2de3

eslintは結構めんどくさいようだ
 prettier は簡単 2022/02/12  0:35

> eslintは、javascriptのための静的解析検証ツールでコーディング段階でソースコードの不整合などをチェックすることができるソフトウェアです

まぁ、一箇所に集約した方がかなり楽だからね きっと高度なことをしてるんだろう

難しいせいで小言をいわれた

> eslintは解析検証ツール

> npmは、node package managerのことです

> node.jsのバージョンを容易に切り替えられるnvm-windowsを導入します。

eslintのために npm を入れるために node を入れるために nvm-windows をいれる

四段重ね (Prettier は1段) 集約のためには仕方ないね

> nvmは、node version managerのことです

> eslintプラグインは、eslint本体とvs codeを繋げてタイムリーなコード入力サポートやエラー検出を実現します。


 nvm use 16.14.0
exit status 1: ?A?N?Z?X???????????????B

読めない

管理者権限か? (エスパー)

管理者権限だった

まぁ、 管理者権限で cmd 立ち上げて nvm use したら

vs code terminal でも


nvm list

  * 16.14.0 (Currently using 64-bit executable)

ってなったんでいいんでない


この 5 LGTMのqiitaの おかげで format on save できました

46分2022/02/12  1:03

2022/02/12も腹痛でやすみ

●husky編 2022/02/13 15:02

途中でみたぞ 

やっぱり作りかけなので調べてやるぞ

husky vscode

husky はvscode拡張機能にはなさそう

なんかhusky は windowsだとバグだらけっぽい

https://tamiblog.xyz/2021/02/17/post-1667/


まぁ、このあとに VSCode ESlint でやってみましょう


まぁ、husky のこと調べてそれで一旦はよしとしようか

https://qiita.com/tags/husky

あんまり流行ってない気が LGTM 51とか

https://www.vektor-inc.co.jp/post/use-husky/

これを読んで勉強したことにする2022/02/13 15:22


> husky は npmパッケージ 
> こういった小さな積み重ねが開発スピートに関わってきますので、大事ですね。

一応 vs codeでやってみようか
npmコマンド

まぁ vscodeだとなんか動かなかったみたいだ

まぁ読んだのでおわり 最初はここまでカチカチにしなくてイイダろう

 「読んで学ぶ」編 2022/02/13 15:30

> 本章の流れは、コード上の小さいパーツから大きいパーツに行くように構成しています。 

値など 2022/02/13 19:23

https://typescriptbook.jp/reference/values-types-variables

> letは変数の初期値なしで変数定義できます。初期値なしの変数の値はundefinedになります。

> 基本はconstで変数宣言をして必要な場合にのみ、letを使うのがオススメです

安全なconst


varの問題点
https://typescriptbook.jp/reference/values-types-variables/vars-problems

グローバルで var innerWidth を定義すると window.innerWidthになる

> letやconstはグローバルなスコープで定義されることはない

> JavaScriptで宣言された変数はスコープの先頭で変数が生成されます。これは変数の巻き上げと呼ばれています

Cは戦闘でしか宣言できなかったね
JSはしらんかった

> varでの変数巻き上げでは参照エラーとならないため、意図せずにundefinedの値を参照し予期せぬバグが発生する危険性があります。

letとconstでは、宣言前の変数を参照するとReference Errorが発生します。


  var x = 1;
  {
    console.log(x);
  }
はエラーにならないが

  var x = 1;
  {
    console.log(x);
    let x = 2; 
  }
は巻き上げがあるのでエラー

let, const はブロックスコープだから上書きしにくい


型推論まできた
https://typescriptbook.jp/reference/values-types-variables/type-inference

17min
2022/02/13 19:40

> let x = 1; // let x: number = 1;と同じ意味になる

型推論は静的型付け


> javascriptのプリミティブ型の1つ目の特徴は、値を直接変更できない

そうなんだ

> オブジェクトには、値を後で変更できるというミュータブル特性(mutable)

> 文字列や数値などのプリミティブ型は、プロパティを持ったオブジェクトとして扱えます。。プリミティブ型をまるでオブジェクトのように扱えるのはjavascriptの特徴

> javascriptには、プリミティブ型をオブジェクトに自動変換する機能があります。この機能はオートボクシング(autoboxing)、自動ボックス化


> bigint型: 9007199254740992nのようなnumber型では扱えない大きな整数型。

しらないぷりミティブ型があった

論理型まできたぞ

2022/02/13 19:52 29min

TypeScriptの型推論とかは、この7つの型の識別しかしないのかな?

> TypeScriptには大文字で始まるBoolean型がありますが、これとbooleanは別の型です。

30分立ったのでおわり 2022/02/13 19:53


数値型から再開 2022/02/14 23:00

当然ながら、JavaScriptのことは、ほぼすべてJS中級者でみた

桁区切りのアンスコはどこで区切ってもいい

Number と numberは別よチュュ位シてね

> 整数について言うと、他言語の64ビット整数型の範囲より狭いので注意しましょう。

> 0.1 + 0.2は0.3になってほしいところですが、計算結果は0.30000000000000004になります 0.1 + 0.2 === 0.3; //=> false

> ちなみに、2進数で有限小数になる0.5や0.25などの数値だけを扱う計算は誤差なく計算できます。 0.5 + 0.25 === 0.75; //=> true

> 整数の計算は誤差が生じない

> (110 * 11) / 10 === 121; //=> true

> 小数計算の誤差問題を包括的に解決したい場合は、decimal.jsのような計算誤差がないパッケージを使うのも手です。

> javaなどの言語では、ダブルクォートで文字列リテラル(string型)を表現し、シングルクォートで文字リテラル(char型)を表現するといったように、使うクォートで型が変わります。

> またバッククォート(`)を使っても文字列型になります。

> 'He said "madam, I\'m Adam."'

シングルクォートでも \' が使えるJS

> ダブルクォートとシングルクォートを使った文字列リテラルは、文字列の途中で改行できません。改行を入れたい場合は、\nなどの改行シーケンスを入れる必要があります。

> バッククォート`で囲んだ文字列はテンプレートリテラル(template literal)と言います。テンプレートリテラルは、改行と式の挿入(expression interpolation)ができます。式の挿入は${式}のように書きます。

> `現在、${count}名が見ています。`

> 基本的に"を使用する。文字列の中に"が含まれる場合は'を使用する。文字列展開する必要があるときは`を使用する。

nullがたまできたが、まだまだ方があるなあ 2022/02/14 23:17


TSのもふくめ15こあるみたい

> typeof null; //=> "object"

> 戻り値のない関数はundefinedになりますが、TypeScriptで戻り値なしを型注釈で表現する場合、undefinedではなくvoidを用います。詳しくは関数の説明をご覧ください。

> undefinedは「値が代入されていないため、値がない」、nullは「代入すべき値が存在しないため、値がない」という微妙な違い

> もしどちらを使うべきか迷ったらundefinedを使っておくほうが無難です

> nullは自然発生しない。undefinedは言語仕様上、プログラマーが明示的に使わなくても、自然に発生してくるものです。 

> undefinedもnullもプリミティブ型の値という点は共通していますが、undefinedは変数でありnullはリテラルです。 

> JSON
オブジェクトプロパティの値にundefinedを用いたとき、そのオブジェクトをJSON.stringifyでJSON化したときに、オブジェクトプロパティは削除されます。一方、プロパティの値がnullのときは、JSON化したときに値が保持されます。

> console.log(JSON.stringify({ foo: undefined }));

{}
console.log(JSON.stringify({ foo: null }));

{"foo": null}


> 特にこだわりがないのなら、typescriptではnullは使わずにundefinedをもっぱら使うようにするのがお勧めです。

>  実際にtypescriptの開発チームでは「nullは使わない」というたった1行のシンプルなガイドラインを示し、数多くの開発者が参加しやすくなるようにしています。 

undefined はそこら中で発生するので、undefinedに統一するのが簡単 2022/02/14 23:41

30分読んだのでおわり null/undefined まで

今日6項目進んだ あと178項目ある
 このペースだと30日かかる
  うーん、速度アップがいるかも…??

ーーーー

2022/02/15 22:29 残り178項目

加速する

1日25項目
 今日は配列リテラルまで

> Rubyのシンボル的なことは、JavaScriptやTypeScriptでは文字列を用いて解決します。

bigint
const x = 100n;

> bigintリテラルをTypeScriptで用いるには、コンパイラーオプションのtargetをes2020以上にする必要があります。

> const y = BigInt("9007199254740991");

BigInt(100) でも

小数はBigIntにはないよ

自動キャストのことが型強制(type coercion)
Stringとかはラッパーオブジェクトで自動ボックス化で活躍

ラッパーオブジェクト型じゃなくてプリミティブ型をつかってくのがよさそうだね

いま 4つ読んだ2022/02/15 22:50

> TypeScriptでは暗黙のanyを規制するオプションとして noImplicitAny が用意されています。tsconfig.json にて noImplicitAny: true を設定することで、TypeScriptが型をany型と推測した場合にエラーが発生するようになります。

> 理由なくanyを使うのは問題ですが、どうしてもanyを使わないとならない場面や、型安全性を妥協した上で、まずは動くコードを形にすることを優先するといったこともありえます。anyをどこまで許容するか、型チェックをどこまで厳格にするかは、チームの熟練度やプロジェクトの方針によるところが大きいです。

> 実際に慣れない頃はコンパイルエラーが出ている原因を調べて解消するのに1日を費やす場合もあります。

> 「がんばらないTypeScript」

オブジェクトまでで7つおわった あと18

> オブジェクト型には、クラスから作ったインスタンスだけでなく、クラスそのものや配列、正規表現もあります。

jS中級者なので知ってる話がおおい 結構はやい

> オブジェクトリテラルがあるおかげで、JavaScriptでは自由度の高いコードが書けるようになっています。

> JSONJavaScript Object Nation

Nationって何?

1ページが短いのではやいかも
  800文字くらい
25項目なら 20000文字 文庫本40ページ分

> let box: { width: number; height: number };

みたいに型注釈する ; がポイントっぽいかな?

> // 型エイリアス
type Box = { width: number; height: number };
let box: Box = { width: 1080, height: 720 };

もある

> let calculator: {
  sum(x: number, y: number): number;
};

> let calculator: {
  sum: (x: number, y: number) => number;
};

もある

> let box = { width: 1080, height: 720 };

で勝手にnumber になる (型推論)

> メソッドの場合は引数の型注釈は必要です。


> let foo: Record;

stringがキーで、 numberがバリューなプロパティを何個もいれたオブジェクトを定義できる

オブジェクトの型注釈 https://typescriptbook.jp/reference/values-types-variables/object/type-annotation-of-objects は大事そうだった

あと 14項目

> let obj: {
  readonly foo: number;
};

とかある

readonlyの項目長い


> let obj: Readonly<{
  a: number;
  b: number;
  c: number;
  d: number;
  e: number;
  f: number;
}>;

で、全プロパティ readonly な a,b,...f プロパティをもつオブジェクトをつくれる

> ユーティリティ型

> let size: { width?: number };

オプショナル

あと11 2022/02/15 23:28


> let obj: {
  [K: string]: number;
};

で、キーが string, 値が numberなプロパティをいくつでもつけられる

> インデックス型のフィールド名の型はstring、number、symbolのみが指定できます。

TypeScript特有の事項が多くなってきた

> let obj1: { [K: string]: number };
let obj2: Record;

おなじ

> const dangerousButton = Object.create(button);
複製用メソッドがある(中級者にもかいてあったかも)

> JavaScriptの開発には次のような要件がありました。ブラウザで動く言語で、構文はJava風に。しかし、Javaほど大掛かりでないようにと。そして、開発期間はというと、10日と逼迫したものでした。

> JavaScriptの開発にあたり、Selfという言語の影響があったとEich氏は言います。

> JavaScriptのプロトタイプベース採用の背景には、言語をシンプルで柔軟なものにしたいという考えが根底にあったわけです。

その結果いろいろな書き方が生まれた(これが柔軟らしい)

> let b: Object;
let c: {};

という書き方もある

> Object型はインターフェース

自動ボックス化で プリミティブ型もOKになる

あと7つ 2022/02/16  0:02

分割代入も入れ後にできる

分割代入に名前の付け替えがある
>   canada: { name: canadaName },

https://typescriptbook.jp/reference/values-types-variables/object/destructuring-assignment-from-objects

オブジェクトのキーと変数名が同じだと、変数名を指定してその名前のキーにその値をいれられる

> const pikachu: Wild = { name, no, genre, height, weight };

> JavaScriptのオプショナルチェーン?. 

便利そう

> const title = book?.title;

titleがなかったら undefined になる

> 関数を呼び出すときにもオプショナルチェーンが使えます。関数に使う場合は、引数カッコの前に?.を書きます。

> const result = increment?.(1);

> 配列要素を参照する際にもオプショナルチェーンが使えます。要素を参照する場合は、カギカッコの前に?.を書きます。

> const title = books?.[0]; 

Null合体演算子と組み合わせると便利

> const title = book?.title ?? "デフォルトタイトル";

> for (const prop in foo) {

propにはキーが入る

>   if (Object.prototype.hasOwnProperty.call(foo, prop)) {

ってやると安全

> for (const [key, value] of Object.entries(foo)) {
> for (const key of Object.keys(foo)) {
> for (const key of Object.values(foo)) {
でも hasOwnProperty いらず


構造的部分型にきたぞ 2022/02/16  0:36

https://typescriptbook.jp/reference/values-types-variables/structural-subtyping

構造的部分型で置換できちゃうから、うっかり動いてしまわないように注意、ってことでは?

終わり 2022/02/16  0:41
 2時間強かかってるが?

ーーー

明日は

配列の型注釈から
https://typescriptbook.jp/reference/values-types-variables/array/type-annotation-of-array

if-else 文まで

型がおわったらJSっぽいからすぐ終わっていきそう

2022/02/16 17:44 再開

2022/02/16 18:21 ほんとうに再開

> let array: number[];
> let array: Array;

2通りある

> プロジェクトでは統一すべし

> JavaScriptの配列はオブジェクトであるため、配列の中身が同じでも、オブジェクトのインスタンスが異なると==では期待する比較ができないので注意が必要です。この点はPythonのリストと同じです。

> このような配列の中身を比べるための演算子やメソッドはJavaScriptにはないため、中身を比較したいときにはlodashのisEqualなどのパッケージを使うのがお勧めです。

> ブラケット[]

> JavaScriptの配列では、存在しないインデックス番号でもアクセスできます。その場合でも、JavaScriptではエラーになりません。得られる値はundefinedになります。

なんか、他言語いずれかでのことを知ってる人向けの資料だね

> string[]型から0番目の要素の型はstringになります。

> 要素アクセスで得た値はstringとundefinedどちらの可能性もありながら、TypeScriptは常にstring型であると考えるようになっています。そのため、要素アクセスでundefinedが返ってくる場合のエラーはTypeScriptでは発見できず、JavaScript実行時に判明することになります。

> この問題を指摘してもらうようにするには、コンパイラーオプションのnoUncheckedIndexedAccessを有効にします。

> string | undefined型のままではtoUpperCaseなどの文字列型のメソッドは呼び出せません。そこで、if文で変数が文字列型だけになるように絞り込みます。

複雑になってきた

> if (typeof character === "string") {

> 配列要素へのアクセスを安全にするために、noUncheckedIndexedAccessを有効にしておくことを推奨します。

> const nums: readonly number[] = [1, 2, 3];
> const nums: ReadonlyArray = [1, 2, 3];


型アサーション as number[];

分割代入辺 2022/02/16 20:38 戻ってきた
https://typescriptbook.jp/reference/values-types-variables/array/destructuring-assignment-from-array

> const [one, two, three] = oneToFive;


> noUncheckedIndexedAccess

では number | undefined になってしまう

> ネストした要素の分割代入の書き方は、ネスト構造と一致するようにブラケット([ ])を重ねます。

> const [, , , four, five] = oneToFive; 


> const [one, ...rest] = oneToFive;

残りが残余パターンでまとまる

> 残余部分の型は配列のnumber[]になります。


ぜんぶ JS中級者でみたメソッドなのだ

> reverse   配列の要素を逆順に並び替える 

便利そう


> const copy = [...original]; // コピーを作る

> const reversed = [...original].reverse();


あと19項目 2022/02/16 20:48 (ループする方法から)


> for (const value of arr) { 

配列だと要素が入る

> forEachには戻り値がありません。for文などと異なり、breakやcontinueは使えません。

 > arr.forEach((value, i) => {

インデックスもとれるぞ

> const arr2 = arr.map((value) => value + value); 

> mapではbreakやcontinueは使えません。

> const concated = [...arr, ...arr2]; 

連結も簡単

> 似たシンタックスとして分割代入で使われる残余パターンの構文がありますが、異なる構文なので注意が必要です。

分割代入の残余パターンとは別


> TypeScriptの配列の型は共変(covariant)です。

> 共変とはその型自身、もしくは、その部分型(subtype)が代入できることを言います 共変であれば、Animal型の変数にはAnimal自身とその部分型のDogが代入できます。

> type Animal = { isAnimal: boolean };
type Dog = { isAnimal: boolean; isDog: boolean };


> TypeScriptが健全性(soundness)と利便性のバランスを取ること目標にして、型システムを設計しているためです。配列が非変であると健全性は高くなりますが、利便性は下がります。

危険だが、便利らしい

> const list: [number, string, boolean] = tuple(); 

配列の各要素の型ッ指定できるタプル

> function tuple(): [number, string, boolean] { 

> 配列の型はarray(T[]), generic(Array)というふたつの書き方がありました 

> const [num, str, bool]: [number, string, boolean] = tuple();
> const [, , bool]: [number, string, boolean] = tuple();

分割代入をかつよう

> Promiseという型の変数はawaitをその前につけるとTが取り出せる 


> const tuple: [string, number] = await Promise.all([
  takes3Seconds(),
  takes5Seconds(),
]);

なるほど

> Promise.all()は先に終了した関数から順番に戻り値のタプルとして格納されることはなく、元々の順番を保持します。



あと15項目 2022/02/16 21:03 次は列挙型

enum

> enum Position { 

TypeScriptにしか enumはないのかな? そうらしい

> 値は0からの連番になります 

> let position: Position; 

> enum Position {
  Top = 1, // 1

とかもある

> enum Direction {
  Up = "UP",
  Down = "DOWN",
  Left = "LEFT",
  Right = "RIGHT",
}

もあるぞ

列挙型はTypeScript独自なのでオススメできないらしい


> 型に関する部分を除けば、JavaScriptの文法から離れすぎない言語になっています。

> 文字列列挙型は例外的に公称型になります。 

> type YesNo = "yes" | "no";

とかオススメらしい

type 宣言 キーワードさらっとでてきたっぽい



> const yes = Symbol();
const no = Symbol();
type YesNo = typeof yes | typeof no;

とかも

> type Position = typeof Position[keyof typeof Position];

むふう


次はユニオン型 あと11項目 2022/02/16 21:10

>  |は型のリストの冒頭に置くこともできます。型ごとに改行するときに、列が揃うので便利です。


type ErrorCode = | 400 | 401;
値を型にすることもかのうだったね


> type List = (string | number)[];

() をつけましょう

> 絞り込み(narrowing)

> if (typeof maybeUserId === "string") {

tsでおなじみの構文


> 判別可能なユニオン型

> オブジェクト型からなるユニオン型を絞り込む際に、分岐ロジックが複雑になる場合は、判別可能なユニオン型を使うとコードの可読性と保守性がよくなります。

>   if (status.done === false && "progress" in status) {

とかでも型を絞り込める
    

この項目長い 4800字

なんか大物が続きそうだ

> タグ付きユニオン(tagged union)や直和型と呼ぶこともあります。


> 各オブジェクト型を判別するためのプロパティ(しるし)を持つ

    このプロパティのことをディスクリミネータ(discriminator)と呼ぶ

> type InProgress = { type: "InProgress"; progress: number };

とか

というか、

> type UploadStatus = InProgress | Success | Failure;
type InProgress = { type: "InProgress"; progress: number };

後で中身を定義してもいいんだね

文字列もリテラルがたナンだね
 文字列 数値 論理値


> nullと非nullの関係にある型もディスクリミネータになれます。
> type Result = 
  | { error: null; value: string } 
  | { error: Error };

片方はnullにならないなら オブジェクト型とかでもいいみたい
undefined もあるよ

> ディスクリミネータを変数に代入し、その変数を条件分岐に使った場合も、型の絞り込みができます。


型のある言語でここまで型のことをちゃんとやってたかな??
 でもそういう機能もあったような気もする


オブジェクトの定義を合成させるインターセクション型 2022/02/16 21:28

> type ThreeDimensionalPoint = TwoDimensionalPoint & Z; 

> プリミティブ型のインターセクション型をつくることもできますが、作るとneverという型ができます。意外なところで役に立ちます。

Required Partial 便利そうだね

> type Optional = Partial<{
  index: number;

> type Parameter = Readonly;


あと8項目 次は型エイリアす e0c 2022/02/16 21:32

> type StringOrNumber = string | number;

さっきからたくさん出てきてる

> stringなどのビルトインの型

> // リテラル型
type OK = 200;

> // 関数型
type CallbackFunction = (value: string) => boolean; 

関数型もまだ染み付いてないけどきいじそう


> 型エイリアスは同じ型を再利用したいときに使うと便利です。型の定義が一箇所になるため、保守性が向上します。

読みやすくもなる(ことがある)


> TypeScriptには、型推論を上書きする機能があります。その機能を型アサーション(type assertion)と言います。

> const strLength: number = (value as string).length;

numberにも 同じ名前のメソッドがあると 型に従ってエラーを出せずピンチ

> const strLength: number = (value).length;


> アングルブランケット構文はJSXと見分けがつかないことがあるため、as構文が用いられることのほうが多いです。

やはり複数の書き方があるJSの子供であるTS

> それでも自分の書いた型アサーションが正しいという場合は、unknown型を経由することで上のようなエラーを出さないようにもできます。

> 型アノテーションはキャストではないため、TypeScriptでは型アノテーションをキャストとは呼ばないことになっています。実行時に型変換をするには、そのためのロジックを書く必要があります。 

コンパイルときにしか聞かないからキャストではないとのこと

> 型に関することはできるだけ、コンパイラーの型推論に頼ったほうが安全なので、型アサーションは、やむを得ない場合にのみ使うべきです。

型アサーションを使う必要が出てきたら、それよりも先に、型ガードやユーザー定義型ガードで解決できないか検討してみるとよいでしょう。

> let value: number;

がカた注釈


> オブジェクトリテラルの末尾にas constを記述すればプロパティがreadonlyでリテラルタイプで指定した物と同等の扱いになります。i

> const pikachu = {
  name: "pikachu",
  no: 25,
  genre: "mouse pokemon",
  height: 0.4,
  weight: 6.0,
} as const;


全部を一括でこていできて便利


あとご項目 2022/02/16 21:41 次は definite assignment assertion


> let num!: number;
//     ^definite assignment assertion
> この変数はこの型であることが確実であることをTypeScriptコンパイラに伝えるということです。

> console.log(num! * 2); // エラーにならない
//             ^非Nullアサーション


> // 型ガード
if (typeof num === "number") 

>   return value !== null && typeof value === "object";

> ここで説明したのはJavaScriptのtypeof演算子です。TypeScriptのtypeof型演算子については、typeof型演算子の説明をご覧ください。

別の typeofがあるらしい

> JavaScriptにはグローバルオブジェクト(global object)と呼ばれるオブジェクトがたったひとつ存在します。ブラウザではwindowオブジェクトがグローバルオブジェクトです。 

全てのグローバル変数を司るグローバルオブジェクト

> グローバル変数は、グローバルオブジェクトのプロパティになります。

> 日付のDateクラスや、デバッグに使うconsoleオブジェクトなどの組み込みAPIはすべてwindowオブジェクトのプロパティです。

> レキシカルスコープ(lexical scope)変数とは、関数を定義した地点から参照できる、関数の外の変数を言います。

> ブロックスコープはif構文などのブレースにも作用します。条件分岐の中で変数宣言された変数は、条件分岐の外からは参照できないので注意しましょう。

> ローカル変数を宣言する場合は、letやconstを用いますが、これを書き忘れた変数代入は、グローバル変数になってしまいます。 TypeScriptでは変数宣言されていない変数に代入しようとすると、コンパイラが指摘してくれます。

> else ifのようにelseとifの間にはスペースが必要です。

> JavaScriptのif-elseは文です。式ではないので、条件分岐を直接変数に代入することはできません。

居ょの文おわり 2022/02/16 22:24

明日は this引数まで

wwwwwwww

2022/02/17 21:47

よんでこ

https://typescriptbook.jp/reference/statements/ternary-operator から

> for-of文 - 拡張for文

for-of が 拡張for文 ということらしい

> for (const [index, word] of words.entries()) {

インデックスと値を一緒に取る方法
 
> switch (条件) {
  case 値A:
    値Aの処理;
    break;

switch のあとに { があって結構珍しい書き方?

> switchのフォールスルー問題

PHPと同じかな?

> TypeScriptでは、コンパイラオプションnoFallthroughCasesInSwitchをtrueにすると、フォールスルーを警告するようになります。このオプションは有効化しておきましょう。

fallthrough できなくなるらしい

> caseの変数スコープはない

>   case 1: {

{ で囲める case


> 例外として投げるオブジェクトはErrorオブジェクトを使うのが一般的です。

Error 以外も投げれそう


> Errorオブジェクトを使ったほうがコードの読み手に意外性を与えないからです。加えて、スタックトレースが追えるのはErrorオブジェクトだけだからです。

意外性最小を目指そう

> TypeScriptではcatchの変数の型はデフォルトでany型になります。

> JavaScriptとTypeScriptではcatchは1つしか書けません。JavaScriptでエラーの型によってエラーハンドリングを分岐したい場合は、catchブロックの中で分岐を書く方法で対応します。

>   } else if (e instanceof RangeError) {

> 唯一never型は代入できます。

> const foo: never = 1 as never;

> never型はどんな型にも代入できます。

> never型の「値が無い」とはどういうことでしょうか。たとえば、例外が必ず発生する関数の戻り値です。戻り値は絶対に取れません。そのため、戻り値の型はnever型になります。

> 終了しない関数も戻り値がnever型になります。

ずっとまわりそう


never型ながい 3600時


void型はundefinedが代入できますが、neverは値を持てません。
意味的に戻り値でのvoidとneverは、戻り値が無い点は同じです。関数が終了するかが異なります。voidは関数が最後まで実行されるという意味です。neverは関数の処理が中断、もしくは、永遠に続くことを意味します。

網羅性チェックに使えるらしい 上級ュ者むけっポイ感じする

> 一歩進んで網羅性チェック用の例外クラスを定義するのがお進めです。このクラスは、コンストラクタ引数にnever型を取る設計にします。

            
> 網羅性チェックを例外にしておくと、未使用変数についてのコンパイルエラーが発生しなくなります。

バッドプラクティス感はある

> このような型チェックのコードを型ガードと呼びます。
> if(typeof month === "string")

よくみるやつ


> date != nullの型ガードを追加することで型エラーを解消できます。
| null のばあい

>  特定のクラスのインスタンスであることを判定する型ガードを書きたい場合はinstanceofを利用します。

クラスの判定もできるTypeScript

> 特定のクラスのインスタンスであることを明示せず、in演算子でオブジェクトが特定のプロパティを持つかを判定する型ガードを書くことで型を絞り込むこともできます。

>   if ("castMagic" in player) {


> 型ガードはインラインで記述する以外にも関数として定義することもできます。

> function isWizard(player: Player): player is Wizard {

便利

> unknownはどんな型も代入できる型

> unknown型はanyを除いて他の型には代入できない

> 同様にunknown型は、プロパティアクセスや関数呼び出しがコンパイルエラーになる。

あと 16項目 2022/02/18  1:06

any, unknown型はどのような値も代入できます。

any型に代入したオブジェクトのプロパティ、メソッドは使用することができます。

> noImplicitAnyがあります。既存のJavaScriptのプロジェクトをTypeScriptに置き換えていくのではなく、スクラッチの状態からTypeScriptで作るのであればこの設定を入れるとよいでしょう。

僕も知ってる設定

> 関数宣言

定まさし

あと14項目 2022/02/18  1:11

引数の型注釈を省略した場合、コンパイラーはany型と暗黙的に解釈します。
コンパイラーオプションのnoImplicitAnyをtrueに設定することで、引数の型注釈を必須にできます。


型推論で ユニオン型になることも

> 関数式を用いて関数を定義するには、function式を用います。関数式は式なので、関数の終わりにはセミコロンを書きます。

; をつけるだけで function敷になる

> アロー関数は関数式に比べて短く書けるのが特徴的です。引数が1つだけの場合は、引数のカッコが省略できます。

色んな書き方があるJS

> さらに、関数内のコードが式1つだけの場合は、ブレースとreturnが省略できます。

シンタックスシュガーだらけ

> アロー関数でカッコを省略した記述をした場合には、引数と戻り値のどちらも型注釈を書けません。

noImplicitAnyが有効になっていても、関数引数に直接アロー関数を書く場合は型注釈を省略できます。

TypeScriptでは、関数の型を宣言できます。関数の型の宣言とは、関数の実装を示さずに、関数のインターフェースを定義することです。

type Increment = (num: number) => number;

> しかし、関数宣言(function文)の型注釈には使えません。

なんでや function敷には使える

> 関数の型宣言を型注釈に使った場合、関数の実装側の引数と戻り値の型注釈は省略できます。 実際のコードでは、省略形で書くのが一般的です。


> TypeScriptでは、アロー関数構文で関数の型を宣言する方法とは別に、メソッド構文でも関数の型を宣言できます。

> // メソッド構文による型宣言
type Increment2 = {
  (num: number): number;
};

> 一般的には、アロー関数構文で型宣言します。アロー関数構文のほうが短くシンプルだからです。

> メソッド構文による型宣言は、オーバーロード関数の型宣言に使われることがあります。

> TypeScriptでは、関数の実装から関数の型を宣言できます。関数の値に対してtypeof型演算子を使います。

> JavaScriptの関数宣言と関数式の違いが現れるひとつの例は巻き上げ(hoisting)です

関数宣言には巻き上げがあり、関数式には巻き上げがありません。

このコードは、hello関数の定義行より前でその関数を呼び出しているのに、エラーにはならず問題なく"Hello World"が出力されます。これは関数宣言には巻き上げがあるためです。


残り9項目 ニ地2022/02/18  1:36

他の言語では関数は特別な立ち位置のことがあります。ある言語では、同じ名前の変数を定義してもエラーにならないのに対し、同じ名前の関数定義はエラーになります。またある言語では、関数を変数に代入できなかったりします。

JavaScriptの関数は値です。つまり、PHPのような他の言語と比べると特別扱いの度合いが少ないです。

JavaScriptで関数の再代入によるバグを未然に回避したい場合は、constと関数式を組み合わせます。関数式については後述します。

ちなみに、TypeScriptではコンパイラーが重複した関数宣言を警告してくれるので、バグの心配はありません。

関数は値なので、関数名のスコープも変数と同じようにスコープの概念があります。たとえば、関数スコープの中で定義された関数は、そのローカルスコープでのみ使うことができます。


https://typescriptbook.jp/reference/functions/function-is-an-object
1行だけでめちゃみじかい 50地


あと6項目2022/02/18  1:49

TypeScriptで戻り値がない関数の戻り値を型注釈するにはvoid型を用います。void型は関数の戻り値を型注釈するためにある特別な型です。


> JavaScriptでは引数が少ない時はその引数にはundefinedが渡され、引数が多い場合は余分な引数は無視されますがここはTypeScriptとJavaScriptとの大きな違いです。

> 引数を省略したいことがあります。そのときはオプション引数とデフォルト引数を使用することができます。

> 可能であればデフォルト引数の使用を検討してください。

> オプション引数は必ず最後に書かなければいけません。つまり、次のようにオプション引数より後ろに普通の引数を書くことはできません。

デフォルト引数とは、関数に値が渡されないときやundefinedが渡されたときに代わりに初期化され使用される値のことです。なおnullが渡されたときはデフォルト引数は適用されませんので注意してください。

> const p0: Point = {
  x: 0,
  y: 0,
};
function distance(p1: Point, p2: Point = p0): number {

 オプション引数と比べてもより簡素に書けるようになります。

また、オプション引数と異なりデフォルト引数は値が渡されたときも渡されなかったときも意図する型(この場合Point型)が入っているのでオプション引数と異なり処理の分岐が不要になります。

> さらに、デフォルト引数があることでデフォルト引数を受け付けている引数は型推論が効き型を書く必要がなくなります。

なるほど、だから引数に方がかかれてないことがあったのね

> function distance(p1: Point, p2: Point = inverse(p1)): number {

もかのう

> デフォルト引数はオプション引数と異なりその引数を最後に書く必要はありません。

イタレリツクセリなデフォルト引数

> distance(undefined, q2);

> 関数をデフォルト引数として使うときは非同期の関数を使うことができません。

こういうところで化まりそう でもまぁ エラーメッセージがあるので大丈夫とは思う

引数の個数が決まっていない引数のことを可変長引数(variable length arguments, variadic arguments)といいます。JavaScriptでは可変長引数は残余引数(rest parameter)と呼びます。

function func(...params) {

受け取った残余引数は配列になります。
残余引数は必ず最後の引数でなければなりません。残余引数を複数持たせることはできません。また、残余引数の後に普通の引数を置くこともできません。

JavaScriptに組み込みのメソッドにMath.max()があります。これは、引数に与えられた数値の中から最大値を返します。この関数は残余引数を要求します。

関数呼び出しのときにひとつの配列にまとめて渡すことはできません。
配列を余剰引数に渡す場合は、スプレッド構文(spread syntax)を用います。スプレッド構文は...と書きます。

const highest = Math.max(...scores);

残余引数もスプレッド構文も...と同じ表記ですが、スプレッド構文は配列を引数にバラすものです。

アロー関数以外の関数とクラスのメソッドの第1引数はthisという特殊な引数を受けることができます

> 引数のthisを指定することによって意図しないメソッドの持ち出しを避けることができます。 
そうなんや

おわり 2022/02/18  2:29

やっぱり二時間くらい?
 もっとかかってるかも ながら

明日は
メソッド戻り型のthis型 まで
 やっぱ26項目にしようか
  ◎クラスの継承まで でかそう
   まぁ速度重視、ってことで
あと103こうもくなので 4日でおわり 
つまり やはり 2/21(月)におわる
 その次の日にこれをブログにしたい

wwwwwwww

2022/02/18 23:25

分割代入引数から
https://typescriptbook.jp/reference/functions/destructuring-assignment-parameters

> JavaScriptでは分割代入構文は関数の引数でも使えます。



> function foo({ a, b }) {
> foo({ a: 1, b: 2, c: 3 });

プロパティをそのまんま入れられる感じっぽい

> function foo({ a: x, b: y }) {

> 配列の分割代入引数は、カギカッコの中に配列要素を代入する変数名を書きます

> function bar([a, b]) {

> bar([1, 2, 3]);

> function foo({ a, b }: { a: number; b: number }) {}
> function bar([num1]: number[]) {}

> function bar([num1, num2]: [number, number]) {} 

2つ指定するのがタプル型 多分

JavaScriptでは、分割代入引数に対応するオブジェクトプロパティや配列要素が無い場合、undefinedが代入されます。一方、TypeScriptでは分割代入引数に対応するオブジェクトプロパティや配列要素が無いと、コンパイルエラーになります。

{} や [] がひきすうになるのが分割代入引数

function foo({ a = 0 }) {

function foo({ a = 0 }: { a?: number | string }) {}

?がいるデフォルト引数には

プロパティの既定値からプロパティの型が予想できる場合、型注釈を省略できる場合もあります。

function foo({ a, b } = { a: 0, b: 0 }) {

引数全体が無い、または、undefinedの場合に採用されます。

bar([1]);

1 undefined

function foo({ a }: { a?: number } = { a: 0 }) {}

> JavaScriptでは、分割代入引数の引数名と同じ変数が定義済みであれば、オブジェクトリテラルのプロパティ名を省略し、変数だけ渡すことができます。

よくみる

> bmi({ weight, height });

長い項目多い
 かんすうのコーナーの中

> JavaScriptやTypeScriptの関数には、Pythonにあるキーワード引数のような機能はありません。その代わり、分割代入引数を応用することで、キーワード引数と同じようなことができます。


python
func(x=1, y=2, z=3)  # => 1 2 3

べんり

キーワード引数と同じような機能はRubyや、Scalaの名前付き引数(named argument)などに見られます

Ruby にあるんだ

Options Objectパターンというデザインパターン

> Options Objectパターンは複数の位置引数を受け取る代わりに、ひとつのオブジェクトを引数に受け取るように設計された関数を言います。

よくみる

func({ x: 1, y: 2, z: 3 });

さらに、Options Objectパターンでは分割代入引数を応用すると、引数の部分をよりシンプルに書けるようになります。

function func({ x, y, z }) {


function func({ x, y, z }: { x: number; y: number; z: number }) {

でも呼び出し側が長くなるね
findUsers({ country: "JP", city: "Tokyo", order: "id", sort: "asc" });

関数宣言側をfunction func({ hoge })に変更する代わりにfunction func({ hoge: fuga })のようにします。

> function func({ x, y = 0, z = 0 }: { x: number; y?: number; z?: number }) {

オプショナルなので?

> function func({ x = 0, y = 0, z = 0 }: Options = {}) {

0を入れられてすごい


> function isDuck(animal: Animal): animal is Duck {

なんか便利そう


アサーション関数
> こちらは例外を投げるかどうかで判定します
>   throw new Error("YOU ARE A FROG!!!");


オーバーロード
> TypeScriptもこの機能を用意しているのですが、大元がJavaScriptであることが災いし、やや使いづらいです。


あと20項目 いまSwpw*オーバーロード


> type Distance = {
  (p: Point): number;
  (p1: Point, p2: Point): number;
  (x: number, y: number): number;
  (x1: number, y1: number, x2: number, y2: number): number;
};


複数の定義ができる


> rejectをするには例外を投げる

中級者でよんだ

>awaitはasync関数の中でしか使えないこと

> トップレベルawaitは触れなくていい

中級者にかいてあった感


いま paa 2022/02/19  0:25

あと15項目

ここで注目するべきはrequest1()関数の戻り値をPromiseと型指定をしている箇所です。
TypeScriptでPromiseの型を指定する場合はPromiseと書きます。TにはPromiseが解決(resolve)された時に渡す値の任意の型を指定します。

async /awaitが存在します。
この構文を利用することで、非同期処理をより同期処理と同じような文脈で書くことができるようになります。

> 関数の前にasyncキーワードをつけることで、その関数は非Promiseの値を返す時にその値を解決したPromiseを返すようになります。Promiseをそのまま返すことも可能です。二重にPromiseがラップされることはありません。

なるほど


> TypeScriptでは、クラスを定義するとクラス名と同じ名前の型が同時に定義されます。

あよ12項目 2022/02/19  0:45

constructor構文
フィールドは宣言時に型を省略した場合でもコンストラクタで値が代入される場合は、代入する値で型が推論されます


あと10高銀 2022/02/19  0:53


> TypeScriptでは、初期化子(initializer)を使うとインスタンスのフィールドの初期値を指定できます。

便利 2022/02/19  0:56

初期化子で値の型が自明な場合、TypeScriptコンパイラーはフィールドの型を推論してくれます。そのため、初期化子を伴うフィールドは型注釈を省略できます。

TypeScriptにはJava風のアクセス修飾子があります。

nameプロパティはpublic宣言されているため、インスタンスされた変数(gorilla)からの読み書きが可能になっています


privateメソッドの多くの使い方としては、自身のクラス内の長いコードを機能別に分ける時に利用します。

メソッドの引数にはアクセス修飾子を設定することはできませんがコンストラクタは特別です。

public  自身のクラス内、継承クラス、インスタンス化されたクラスのどれからでもアクセス可能

読み取り専用フィールドは、コンストラクタかフィールド初期化子でのみ値を代入できます。

クラスはオブジェクト
一方、TypeScriptでは型安全のためにこうした動的な拡張ができないようになっています。

あと4項目 2022/02/19  1:09

TypeScriptでは、Java風の静的フィールドの書き方ができるようになっています。TypeScriptで静的フィールドを宣言するにはstaticキーワードを用います。

  static field: number = 123;
  static field = 123;

TSってJSをだいぶJavaふうにしてるんだね
  private static field: number;
  static readonly field: number;

readonly static メソッドなどはない


fluent interfaceとは「流れるようなインターフェース」という意味で、method chaining(メソッドの連鎖)という小技を使って、可読性の高いコードを実現するメソッドの作り方のことです。


  protected value: number;

に入ったものが勝手にかえるというか this が this.value と評価される感じ

return thisでチェインできる

>   public subtract(value: number): this { 

とすると継承しても安心


> サブクラスにコンストラクタを書く場合、スーパークラスのコンストラクタは必ず呼び出す必要があります。スーパークラスのコンストラクタはsuper()で呼び出します。 

中級者でみた

2022/02/19  1:19 よみおわ



https://typescriptbook.jp/reference/object-oriented/class/class-inheritance

2022/02/20  1:58

今日は Readonly まで

> TypeScriptでは、クラスに1つでも非パブリックなプロパティがあると、そのクラスだけ構造的部分型ではなく公称型(nominal typing)になります。

なるほど

> TypeScriptにはabstract修飾子があり抽象クラスを表現できます。
抽象クラスとは直接インスタンス化(new)することができず、必ずスーパークラスとして利用することを保証するものです

> 抽象クラス内のメソッドにもabstract宣言を行うことができます。interfaceと同じようにサブクラスは抽象メソッドを実装する必要があります。

final sealed ない (継承付加にさせる)

もう4つ終わった 2022/02/20  2:05

JavaPHPなどの言語では、インターフェースが定義できますが、JavaScriptにはそれに相当する構文がありません。一方、TypeScriptにはインターフェースがあります。

interface SomeInterface {

なるほど便利 だけどJSとはどんどんべつにナッテくね
 interface/ ができそう

TypeScriptではメソッドだけでなく、パブリックフィールドも定義できます。

TypeScriptは構造的部分型なので、インターフェースと実装関係がないオブジェクトの型注釈としても利用できます。

const taro: Person = {

組み込みapiで 13
 
class Developer implements Human {

class TypeScriptProgrammer implements Human, Programmer {

TypeScriptでは、extendsキーワードを利用して定義済みのインターフェースを継承して、新たにインターフェースを定義することができます。

プロパティを部分型に宣言しなおす
ある型からその型のリテラル型にすることも、ユニオン型から部分的に選択することもTypeScriptではそれぞれサブタイプにしていることと同じ意味があります サブクラスにすることもできます。

interface IndexPage extends WebPage {
  path: "/";

ES2016.array.ts

> type Array = ES2016Array & ES2019Array; 


インターフェイス判定をするには型ガードを自前で実装する必要があります。以下はその例のisStudent()です。

インターフェースは型の宣言であり、型エイリアスは型に名前をつける機能です。この定義に立ち返って使い分けをしましょう。

ジェネリクスもないJavaScript

はんぶくくきた 2022/02/20  2:40
つかれるまでやろうか

MapはJavaScriptの組み込みAPIのひとつで、キーと値のペアを取り扱うためのオブジェクトです。Mapにはひとつのキーについてはひとつの値のみを格納できます。

const map = new Map();

長い

https://typescriptbook.jp/reference/builtin-api/map
5900地

コンストラクタにキーと値の[タプル型][K, V]の配列[K, V][]を渡すとMapオブジェクトが作られます。

Mapの型変数を省略した場合、TypeScriptはコンストラクタ引数からMapの型を推論します。

コンストラクタ引数を省略した場合、空のMapが作られます。

function doSomething(map: Map) {}

めちゃ使いそう

そのため、Mapはnullとundefinedを異なるキーとみなします。

NaN同士は厳密等価ではありませんが、例外的に同じキーとみなされます。

等価と厳密等価がある

オブジェクトは等価でも厳密等価でもないため、別のキーとみなされます。

たまに使いそう

Mapにキーと値のペアを追加するにはsetメソッドを使います。

map.set("a", 1);

getメソッドは、キーが存在しない場合、undefinedを返します。

deleteの戻り値は、キーが存在した場合true、そうでない場合falseになります。


> この場合、getで値を取得して、その値がundefinedでないことをチェックするとうまくいきます。 

Mapに登録されている要素をすべて削除するにはclearメソッドを使います。

keysメソッドはキーの反復可能オブジェクトを返します。
valuesメソッドは値の反復可能オブジェクトを返します。
entriesメソッドはキーと値の反復可能オブジェクトを返します。

よくみる

> for (const [key, value] of map) { 

とうろくされたzilyunn

const map2 = new Map(map1);
シャローコピー

MapをJSON化する場合は、一度オブジェクトにする必要があります。


const keyValues = [...map];
[["a", 1], ["b", 2], ["c", 3]]

> const map = new Map(Object.entries(obj));

オブジェクトがMapになる

const obj = Object.fromEntries(map);


この Map がおわったらあと12こう木 今日は

反復の順序が複座つなオブジェクト


メソッドで操作するMap、 言語仕様だから専用の書き方があるオブジェクト
  Mapは組み込みapi


一旦…最後までか? Errorまでか? 2022/02/20  3:01

Setもそこそこでかい
https://typescriptbook.jp/reference/builtin-api/set

2500地

Setには重複する値が格納できません。Setに格納された値は一意(unique)になります。


コンストラクタに配列を渡すと、値がSetに格納されます。


空のSetオブジェクトのTypeScript上の型はSetになります。これでは後からSetに値を追加できないので、空のSetを作るときは、Setの型変数を指定する必要があります。

const fruits = new Set();

Mapのキーな指板 Set

JSONにするとき
const array = [...fruits];
console.log(JSON.stringify(array));

「Setに渡した値は重複しない」という特性を使って、配列から値が重複する要素を取り除く処理に応用できます。

const array2 = [...new Set(array1)];


あと11項目 2022/02/20  3:04


TODO: 実務ではdate-fnsの使用を推奨する

ErrorはJavaScriptの組み込みAPIのひとつで例外を取り扱うためのオブジェクトです。

JavaScriptにもある

組み込みAPIとしてErrorには次のサブクラスがあります。

    EvalError
    InternalError
    RangeError
    ReferenceError
    SyntaxError
    TypeError
    URIError

便利そう

class CustomeError extends Error {

わかる

console.log(err.stack);

name と message を一気にだせて便利な .stack


もし捕捉した値があるクラスのインスタンスまたはある型であるかを判定したい場合はinstanceof, keyofあるいは型ガードを使います。

  if (e instanceof Error) {

モジュールは、importまたはexportを1つ以上含むJavaScriptファイルを言います。

ナウくて、前ははっきりと知らなかった部分

importなど export require めちゃなが
9000じ
https://typescriptbook.jp/reference/import-export-require
2022/02/20  3:37

export const foo = "foo";

JavaScriptのモジュールは、明示的にexportをつけた値だけが公開され、他のモジュールから参照できます

Javaなどの他の言語では、モジュール(パッケージ)のメンバーがデフォルトで公開になり、非公開にしたいものにはprivate修飾子をつける言語があります。そういった言語と比べると、JavaScriptは基本方針が真逆なので注意が必要です。


モジュールのコードが評価されるのは、1回目のimportのときだけです。2回目以降のimportでは、最初に評価した内容が使われます。言い換えると、モジュールは初回importでキャッシュされるとも言えますし、モジュールはいわゆるシングルトン(singleton)的なものとも言えます。

もしjQueryに依存するパッケージがあるとすれば、jQueryの宣言より下に書く必要があります。

パッケージが少なければまだしも、増えてくると依存関係が複雑になります。もしも読み込む順番を間違えるとそのhtmlでは動作しなくなるでしょう。

require()
Node.jsでは現在でも主流の他の.jsファイル(TypeScriptでは.tsも)を読み込む機能です。基本は次の構文です。


const package1 = require("package1");

このとき.js, .jsonとTypeScriptなら加えて.tsを省略することができます。TypeScriptでの開発においては最終的にJavaScriptコンパイルされることを考慮すると書かないほうが無難です。


.jsを.tsと同じ場所に出力するようにしているとTypeScriptにとって同じ名前の読み込ことができるファイルがふたつ存在することになります。このときTypeScriptは.jsを優先して読み込むので注意してください。

また指定したパスがディレクトリで、その中にindex.js(index.ts)があれば、ディレクトリの名前まで書けばindex.js(index.ts)を読み込んでくれます。

他のファイルを読む込むためにはそのファイルは何かを出力している必要があります。そのために使うのがこの構文です。

module.exports = (i) => i + 1;

const increment = require("./increment");

このmodule.exportsはひとつのファイルでいくらでも書くことができますが、適用されるのは最後のもののみです。

exports.increment = (i) => i + 1;

const util = require("./util");

console.log(util.increment(3));

const { increment } = require("./util");

console.log(increment(3));

const { increment: inc } = require("./util");

ES6で追加された機能のため、あまりにも古いブラウザでは動作しません。

require()はファイル内のどこにでも書くことができる一方でimportは必ずファイルの一番上に書く必要があります。

import * as package1 from "package1";
import package2 from "package2";

微妙に違う

export default (i) => i + 1;

node.js の require に default 的なやつと 名前付きのやつがあったので、 ES Moduleでも二通りアルンだね

まぁ、突っかかったときとかは https://typescriptbook.jp/reference/import-export-require を読み返そう

2022/02/20  3:54


> ES Moduleではimportをファイルの先頭に書く必要があります。これは動的に読み込むファイルを切り替えられないことを意味します。このimport()はその代替手段にあたります。 

require()と異なる点としてはimport()はモジュールの読み込みを非同期で行います。つまりPromiseを返します。

import("./util").then(({ increment }) => {
  console.log(increment(3));
  // @log: 4
});

なるほど


> Node.jsでES Moduleを使う
> ES Moduleとして動作させたいJavaScriptのファイルをすべて.mjsの拡張子に変更します。

ややこしい
importで使うファイルの拡張子が省略できないことに注意してください。

> "type": "module"
package.jsonにこの記述を追加するとパッケージ全体がES Moduleをサポートします。 

なお"type": "module"の省略時は"type": "commonjs"と指定されたとみなされます。これは今までとおりのNode.jsです。

CommonJSで書かれたJavaScriptを読み込みたくなったときはCommonJSで書かれているファイルをすべて.cjsに変更する必要があります。

ES Moduleにはrequire()がなく、一手間加えて作り出す必要があります。

import { createRequire } from "module";

すべてをES Moduleとして読み込むこの設定は、多くのパッケージがまだ"type": "module"に対応していない現状としては非常に使いづらいです。

TypeScriptでは一般的にES Module方式に則った記法で書きます。

執筆時(2021/01)

ブラウザ用であればES Moduleを、サーバー用であればCommonJSが無難な選択肢になります。

ひとつのファイルから複数exportできる

namedがつよそう

ロジックが変わったこととそれによる修正を強制したいのであればnamed exportを使う方がわかりやすく、そしてエディター、IDEを通して見つけやすくなる利点があります。逆に、公開するパッケージのようにAPIが一貫して明瞭ならばdefault exportも価値があります。


2022/02/20  4:08
シングルプロセス
3700地

https://typescriptbook.jp/reference/single-process-and-callback

02:00 にはじめてる
あと7項目

ブロッキングの逆の概念です。Node.jsはノンブロッキングI/Oを取り扱うことができます。

いままでsetTimeout()は第2引数のミリ秒だけ遅延させてコールバック関数を実行すると説明していましたが、厳密にはミリ秒経過後にメッセージキューに戻すだけで、そのコールバック関数が即座に実行されるわけではありません。

終わった 2022/02/20  4:17
9分 ながら つまり、 400地/分かな
 つまり、1時間 24000地、 2時間で 50000地 一日に文庫本 100ページ読んでることになる


TypeScriptでは型から別の型を導き出す機能があります。既存の型を再度利用して、新たな型を生み出すことを本書では「型の再利用」と呼ぶことにします。

型の再利用とは、変数の再利用のメタファーなのです。

あとご項目 2022/02/20  4:21

TSって 方追加ダケタなくて、インターフェイスとか色々も追加されてるのね

TypeScriptのtypeofは変数から型を抽出する型演算子です。

type Point = typeof point;

ここで説明したのはTypeScriptのtypeof型演算子です。JavaScriptのtypeof演算子と同じ名前ですが、まったく別のものなので注意してください。

めちゃむず

べつの名前にすればいいのに

type PersonKey = keyof Person;

type BookKey = "title" | "price" | "rating";


interfaceとtypeの違い の次が 
    tsconfigの設定項目に関して
なので、この辺飛ばしてそうかも??

> インデックス型にkeyofを用いると、インデックスキーの型が返ります。 キーがstringのインデックス型は、stringではなくstring | numberが返ります。number型のキーアクセスのobj[0]はobj["0"]と同じになるからです。

any型にkeyofを使うとstring | number | symbol型が返ります。

このメモも 42400文字ある既に 2022/02/20  4:25

keyofを使うとそもそも書き写す必要がないため、便利な上に安全なコーディングができます。

ユーティリティ型(utility type)は、型から別の型を導き出してくれる型です

functionが実行時の世界の関数だとしたら、ユーティリティ型は型の世界の関数といったイメージです。 

Requiredは、Tのすべてのプロパティからオプショナルであることを意味する?を取り除くユーティリティ型です。

type RequiredPerson = Required;

Readonlyの効果は再帰的ではない

やっとおわり 
2022/02/20  4:28
2時間はん ながら

明日は
noUnusedParameters
まで
確かにあと2日でおわりそう

2022/02/20 19:31

開始

Partialは、オブジェクト型Tのすべてのプロパティをオプションプロパティにするユーティリティ型です。

PartialをOptions Objectパターンに応用すると、省略可能でありながら見やすい関数を実装できます。

急にながくなった

Partialを使って見た目をよくできます。


}: FindUsersArgs): Promise {

}: FindUsersArgs = {}): Promise {

> RecordはプロパティのキーがKeysであり、プロパティの値がTypeであるオブジェクト型を作るユーティリティ型です。

オブジェクト型
type Person = Record<"firstName" | "middleName" | "lastName", string>;

Pickは、型TからKeysに指定したキーだけを含むオブジェクト型を返すユーティリティ型です。

便利そう

型引数Tにはオブジェクト型を代入します。

type Person = Pick;

このようにすればBookInputDataは少なくともBookとコード上の繋がりができる上に、authorプロパティの型変更を自動で追従してくれるようになります。

Omitは、オブジェクト型TからKeysで指定したプロパティを除いたオブジェクト型を返すユーティリティ型です。

OmitのKeysにTには無いプロパティキーを指定しても、TypeScriptコンパイラーは指摘しません。たとえば、Keysにタイポがあっても検出できないので注意が必要です。



Extractは2つのユニオン型の共通部分を導き出すことにも使えます。


次は Mapped type 
https://typescriptbook.jp/reference/type-reuse/mapped-types

あと20項目 2022/02/20 19:59

入力の形式が決まっているのであればMapped typeの使用を検討できます。

べんりそう

type SystemSupportLanguage = "en" | "fr" | "it" | "es";


type Butterfly = {
  [key in SystemSupportLanguage]: string;

TypeScriptのインデックスアクセス型(indexed access type)は、プロパティの型や配列要素の型を参照する方法を提供します。

type A = { foo: number };
type Foo = A["foo"];

keyof型演算子と組み合わせると、オブジェクトの全プロパティの型がユニオン型で得られます。

> 配列型の要素の型を参照するのにもインデックスアクセス型が使えます。要素の型を参照するには、配列型に[number]をつけます。

めちゃむず

type StringArray = string[];
type T = StringArray[number];

type State = typeof stateList[number];
type State = "open" | "closed"

type Tuple = [string, number];
type T = Tuple[0];


型の安全性とコードの共通化の両立は難しいものです。

型の安全性を重視しようとすると、同じようなコードを量産する必要が出てコードの共通化が達成しづらくなります。

ジェネリクスの発想は実はとてもシンプルで、「型も変数のように扱えるようにする」

function chooseRandomly(v1: T, v2: T): T {

chooseRandomly("勝ち", "負け");

chooseRandomlyのは型変数名の定義です。慣習としてTがよく使われますが、AでもTypeでも構いません。関数の引数の型や戻り値の型として書かれたTは型変数を参照しています。


Arrayは特別に別の記法で型表記をすることもできます。これらについては配列のページに詳細がありますので併せて参照ください。

ジェネリクスの型定義はひとつである必要はなく、複数の型定義を持つことも可能です。

型変数(type variables)は、もうひとつの便利な入れ物です。ただし、入れられるのは「値」ではなく「型」という違いがあります。

この関数を利用するコードは、numberなどTに好きな型を代入することができます:

const value = printAndReturn(123);

TypeScriptでは、型引数にも型推論が行われます。型引数推論(type argument inference)と言われます

変数の123から型変数Tの型はnumber型になることがコンパイラからは推測可能なので、次のコードのように型引数の記述を省略することもできます。

const value = printAndReturn(123);

function func5<かた>(x: かた) {}

型変数名に使えないものは数字ではじまるもの、classなどの予約語です。

単純なジェネリクスで、型変数が2つある場合は、TとUが用いられることがあり、その理由はアルファベット順でTの次がUだからです。この規則にしたがって、3つ目の型変数はVする場合もあります。

複数の型変数がある場合、型変数に意味のある名前をつけることもあります。その場合、TKey、TValueのようにT接頭辞を付けた命名規則がしばしば使われます。ただし、これは「型変数名にはTを用いる」という慣習ほどは一般的でないように思われます。

型変数名を単語にする場合は、大文字始まりのキャメルケースにすることが普通です。

ジェネリクスはそもそも抽象的なものごとを扱うため、具体的な名前が付けられないため、意味を持たないTのほうがいいという考え方があります。

Elementのような型変数名を定義すると、一見するとそれがクラス名のように見えてしまいます。混乱を避けるためにもTのほうがよいという意見があります。

型変数にも同じことが言えて、型変数のスコープが広いものは単語にし、短いジェネリック関数の中でしか使わない型変数は1文字が妥当という考え方があります。

コンパイラは存在しないプロパティへの参照が発生する可能性を検知してコンパイルエラーとしているのです。

function changeBackgroundColor(element: T) {

このextendsキーワードはインターフェースに対しても使います。インターフェースは実装のときはimplementsキーワードを使いますが型引数に使うときはimplementsを使わず同様にextendsを使います。

type MyErrorEvent = {

type MyErrorEvent = {

class Aubergine {

デフォルト型引数は左から順に参照されるため、左にあるジェネリクスが右のジェネリクスを指定することはできません。

2022/02/20 21:20
tsconfig.jsonを設定する
に到達
https://typescriptbook.jp/reference/tsconfig/tsconfig.json-settings

4400もじ 

あと12項目

Node.jsはそれ自身ではTypeScriptをサポートしているわけではないため、TypeScriptの導入をする時はTypeScriptの設定ファイルであるtsconfig.jsonが必要です。


typescriptがグローバルインストールされていればnpx不要

使いたいtargetには使いたい機能がない、でも使いたい。そのような時はlibオプションを指定することで使うことができるようになります。

むずかめんどそうポイント

指定したtargetでは実装されていないライブラリや、必要がないライブラリを除外したいときに使います。

軽くなりそう

>     "target": "es2018",
>     "lib": [
      "es2018",
      "esnext.AsyncIterable",
      "esnext.Array",
      "esnext.Intl",
      "esnext.Symbol"
    ]


あえて古いコードで動かしている、または古いNode.jsを使っているといった事情がなければ最新に近い物を指定することは問題ありません。

Node.js 14.xであれば"target": "es2020"は無難な選択肢です。

またBabelなどの専用のコンパイラやモジュールバンドラに処理を任せたい場合はtargetに"esnext"を指定して、そこからバージョンに合わせたコンパイルを各々にお願いすることになります。

Node.jsのバージョンごとにサポートされているEcmaScriptの機能は node.green で確認することができます。

とくにnpm installしたものであればこれらをパッケージと呼びます。

モジュール読み込みの仕組みが異なっているライブラリの互換性は一般的にはないものと考えてください。そしてこれはフロントエンドとバックエンドでは異なります。

es2015, es2020, esnext
通称esmoduleと呼ばれるモジュール読み込みの解決方法です。

スクラッチから作るということは現在の資産との整合性の都合、しがらみが一切ない状態です。ここから作るならこれだけは満たしておけば型に満ちたプログラミングができるという紹介です。

strictはstrict系のコンパイラオプションを一括で有効化するコンパイラオプションです。
個々の設定が優先されます。

戻り値の型注釈を必須にしたい場合は、noImplicitReturnsを有効にしてください。

再開 2022/02/21  0:36
あと9項目

さすがに個々の設定は短いかな?

とりあえず、できるものならtrueにするのがよさそう

TypeScriptの関数には引数の双変性(parameter bivariance)という性質があります

TypeScriptの関数型は、引数の反変性と引数の共変性の両特性を持っています。この両特性は一言で、引数の双変性と言います。

引数の共変性を許さないstrictFunctionTypes

strictFunctionTypesのチェックが働くのは関数型だけです。メソッド型には働きません。

プロパティがオプションの場合も警告が出ません。

まぁ、すいしょうなのは極力trueにするよね

2022/02/21  0:48
あと4つ

alwaysStrict
'use strict'を各ファイルの先頭に付加します。

便利

終わり 2022/02/21  1:05
機能ほど、長い項目なくて楽だった

明日は25項目で最後まで。

2022/02/21 22:57

やってこ

https://typescriptbook.jp/reference/tsconfig/exactoptionalpropertytypes
から

型定義ファイルを同梱することにより補完やコードチェックとして利用することができます。

ヘッダーファイルだ

tsc -d
でつくれる

    JavaScriptで書かれたパッケージだが、 DefinitelyTypedに登録されている

TypeSearchからパッケージ名を検索しインストールを行います

npm install @types/express --save-dev # 型定義ファイルのインストール

なるほど @types/ の意味がやっとわかったぞ

型定義ファイルを一緒に出力しましょう。そのためにはtsconfig.jsonにあるdeclarationの項目をtrueに変更します。


"sourceMap": true,

> 確かにフロントエンドを動的にしたいのであればほぼ避けて通れないJavaScriptと、バックエンドでも使えるようになったJavaScriptで同じコードを使いまわせれば保守の観点でも異なる言語を触る必要がなくなり、統一言語としての価値が大いにあります。

むふう

  "extends": "./tsconfig.base.json",

このようなtsconfig.xxx.jsonができていれば、あとは次のようにファイル指定してコンパイルをするだけです。

tsc -p tsconfig.cjs.json

module bundlerは容量削減のための涙ぐましい努力を続けています

Tree Shakingとは使われていない関数、クラスを最終的なjsファイルに含めない機能のことです


ここで言及している副作用とは以下が挙げられます。

    exportするだけで効果がある
    プロトタイプ汚染のような、既存のものに対して影響を及ぼす

  "sideEffects": ["./xxx.js", "./yyy.js"],


Generatorを使用した関数はアロー関数での表記ではなく、必ずfunction*() {}と書く必要があります。次は可能なGeneratorの記述方法です。

中級者でみた

現在でも大量のデータを取得したいときに一度ではなく、小出しに取得したいときにGeneratorは使い道があります。


プロパティへのインターセプター(参照・代入・監視などの意味)としGetter/Setterがあります。

あと 12項目 2022/02/21 23:56

自分たちでこのパッケージに手を加えることは容易ではないため (できなくはありません) 。制作者にプルリクエストを出してバグフィックスが行われるまで開発を止めるというのも現実的ではありません


浅いコピーの実装は昨今のJSでは大変楽になっており、次のコードで完成です。

const shallowCopied: object = { ...sample };

スプレッド構文は配列をはじめとするコレクションに対しても使うことができます。

const merged = { ...obj1, ...obj2 };

const merged = {
  ...obj1,
  ...obj2,
  ...obj3,
  // ...
};

あと10項目 2022/02/22  0:08

2つ目の方法はlodashを用いるものです。lodashはさまざまな便利関数を提供するライブラリで、その中のひとつにpickというオブジェクトのサブセットを得るための関数があります。

npm install -D @types/lodash

型情報もゲットしよう

関数やメソッドでオブジェクトひとつを引数として受け、戻り値もオブジェクトひとつとする RORO という考え方があります。RORO は Receive an Object, Return an Object の略です。この考えは JavaScript ならびに TypeScript では大きな恩恵をもたらします。

TypeScriptでは値と型に同名を与えてその両方を区別なく使うことができるテクニックがあります。これをコンパニオンオブジェクトと呼びます。
これは、クラスを作るほどでもなけどそれっぽいファクトリーメソッドとオブジェクトが欲しいときに重宝します。

type Account = typeof account;

> } as const;
type Account = typeof account;

リテラル型になる

>   plan: "Standard" as "Free" | "Standard" | "Premium",

この const の 型への変換べんりだな typeof

keyofはオブジェクトの型に使うとそのオブジェクトのキーをユニオン型にして返します。上記のTypeOfLanguage型があれば

type Language = keyof TypeOfLanguage;

type Language = keyof typeof conf;

keyofは値ではなく (オブジェクトの) 型に対して使用できる


type ConfirmationMessage = typeof conf[Language];

type Currency = typeof currencies[number];

numberをいれると 0とか 1とかの代わりのユニオン型になるらしい

() 即時実行関数の一部 (IIFE: immediately invoked function expression) js
定義されるとすぐ実行される即時実行関数式(IIFE; Immediately Invoked Function Expression)の一部に用いられる書き方です。

- 修飾子の削除 ts

readonlyや?などの修飾子を削除します。

type MyRequired = {
  [k in keyof T]-?: T[k];
};
type Writable = {
  -readonly [k in keyof T]: T[k];

/** JSDoc
慣習的にJSDocなどのドキュメンテーションコメントの開始を表す記号です。これはJavaScriptやTypeScriptの構文ではなく、複数行コメントを用いたドキュメンテーションに慣習的に用いられるものです。


>> ビット右シフト演算子 (right shift) js

左の値のビットを右の値の数だけ右にずらします。

const a = 8;

00001000
const b = 3;
console.log(a >> b);

00000001

?? Null合体 (nullish coalescing operator) js

左の値がnullまたはundefinedのときに右の値を返します。そうでない場合は左の値を返します。

console.log(undefined ?? 1);

1
console.log(2 ?? 1);

2

const user2 = { name: "kaori" };
user2.name ??= "taro";
console.log(user2.name);

kaori

https://typescriptbook.jp/symbols-and-keywords


@ デコレーター (decorator) ts
デコレーターはクラスやクラスメンバーに注釈を追加するもので、デコレーターを使うのに用いられる記号です。

そいうのもあるのね

2022/02/22  0:46
もうすぐで二時間かな?

インデックス型(index signature)の開始に用いられる記号です。

type StringKeysAndStringValues = {
  [key: string]: string;
};

また、慣習的に使わない変数の受け取り先に使われることがあります。たとえば、2つの引数を受け取るコールバック関数で、第2引数だけを使う場合、第1引数をアンダースコアにする書き方をするコードが中にはあります。

[1, 2, 3].map((_, index) => {
  //  _ は 1, 2, 3のような要素値。それを使わないという意味で _ にしている


if文やfor文などの構文を伴わないブロック文は、単に変数のスコープを分けることを目的にしていることがあります。

{
  const value = 1;
}

~~ Double Tilde js
ビット否定演算子を2つ重ねたもので、小数点以下を消し去る計算をするイディオムです。JavaScriptにこういう演算子があるわけではなく慣習的なものです。double tildeの計算結果は、正の数についてはMath.floorと同じに、負の数はMath.ceilと同じになります。


typeof typeof演算子 (typeof) js

与えられた値の型を表す文字列を返します。

console.log(typeof 123);

"number"

typeof typeof型演算子 (typeof) ts
変数から型を抽出する演算子です。

なぜ「これはTSの方のtypeof」とか見分けられるのか
 JSのは変数に使えないのかな?


void void演算子 (void) js

戻り値をundefinedにします。

console.log(void 123);


TypeScript Playground
https://www.typescriptlang.org/play

    エディターのコードを文字列圧縮ライブラリで圧縮して文字列をURLに設定する
    URLを共有する
    共有されたURLが開かれる時に圧縮された文字列をデコードしてエディターに展開する

こんなにちっちゃく圧縮できるんだね

おわった! 2022/02/22  0:54

JavaScript中級者になろう 17章を読んだ(DOM4, Web Components)

前: JavaScript中級者になろう 16章(後半)を読んだ (ES2015-17) - t_hazawaの日記

経緯

  • JS力を付けたかった
  • ES2017までの文法はわかったのだと思う
  • でも、世間で使われてるライブラリは多分これからだ!

2022/01/21 21:35

第十七章 DOM4とHTML

十七章第一回 MutationObserver

https://uhyohyo.net/javascript/17_1.html

  • いきなり分からない言葉がでた
  • html5の仕様には、各要素の定義と同時にその要素のdom定義も定められています

  • domも数回のバージョンアップを経験しており、伝統的にdomのバージョンはレベルと呼ばれています 第十章で紹介したXPath、またtextContentなどがレベル3にあたります。レベル3までのDOMは2004年までに策定完了しており、比較的古典的な概念でした。

  • Level 4で一気に進化したっぽい 2022/01/21 21:41
  • ちなみに、W3C仕様では、DOM3までは正式名称を「Document Object Model Level 3」といったのに対し、DOM4はそれが正式名称 HTML5と同様、WHATWGによるLiving Standardも策定

  • HTML5で新しく追加されたtime要素 ただ、このtime要素に対するブラウザ側の視覚的対応はあまり進んでいません

  • DOMContentLoaded, load イベント
  • DOMContentLoadedはdocumentで発生し、loadはwindowで発生する

  • こういう風にDOMをいじりたい場合、画像やCSSが読み込まれているかどうかは関係ないため、DOMContentLoadedがよく使われます。

  • querySelectorAll
  • jQueryからやってきたみたいなものだ (名前が長い)
  • 返り値はどちらもNodeList getElementsByTagNameで返されるものとquerySelectorAllで返されるものは、動的かそうでないかという違いがあります getElementsByTagNameで返されるNodeListは動的ですが、querySelectorAllはそうではありません 動的というのは、呼び出しの後に起きた変化が反映される

  • 日時時刻ばかりでなく時間(何分とか何時間とか)を表す文字列かもしれません

  • for(const time of Array.from(times)){

  • for-of 分の ここに const を書くのね
  • time.title = date.toString();

  • querySelectorAll でとったものも .titleとすればいじれるのね?
  • この例で何が問題かというと、ページを読み込んだ時点であったtime要素には対応できますが、逆にいうとそれ以外は対応できません 今の時代、ページはjavascriptによってどんどん書き換えられます

  • frontendっぽいはなし
  • 新しい要素)がページ(domツリー)に追加されたことを検知する方法があればいい

  • DOM3にも Mutation Events というものがあった 
  • 新しい要素が追加されるとDOMNodeInsertedというイベントが発生 パフォーマンスに問題があるとかで、現在では非推奨

  • Mutation Observerは、DOMに対する変更を検知し、コールバックにより通知

  • var mo = new MutationObserver(function(records){}); DOMツリーに変更があるたびにこの関数が呼ばれます MutationRecordの配列

  • MutationRecordはどんな変更が加えられたのかを示すオブジェクト

  • 実際に監視を開始するには、observeメソッドを呼び出します。第1引数は監視するノード、第2引数はオプションオブジェクト

  • なんか、 ESにネイティブである機能、関数と、ライブラリの関数かの見分けが付けにくい感じがする。
  • childList: true とか attributes: true とか characterData: true とかでなにの変化を検知するか指定できる
  • まだまだめちゃながい
  • 子孫は検知するオプションもある
  • subtree から 2022/01/21 22:22

2022/01/22 20:07

  • discoonect() でおわり
  •     //テキストノード等の場合querySelectorAllがないので確認する
      if(node.querySelectorAll){
    
  • これでメソッドの存在を確かめられるわけね

yomiowa 2022/01/22 20:59

十七章第二回 DOM4的なメソッド

https://uhyohyo.net/javascript/17_2.html

5000字くらい

  • dom4では基本的な機能に対して新しいメソッドがいろいろ追加されました

  • ちなみに、これらのメソッドはjqueryという有名なライブラリの影響を受けているようです

  • DocumentTypeはDOCTYPE宣言、すなわち<!doctype html>の部分を表すノードです。こんなノードもあったのですね とはいえ、HTML5の時代においてはこのノードはほとんど形骸化してしまった

  • 書かなくなったのかな?
  • 最後のProcessingInstruction(処理命令)はXML文書でのみ登場するもので、こういうやつを表すノードです。

  • <?xml-stylesheet href="foo.xsl" type="text/xsl" ?>
  • このように<?で始まり?>で終わるのがProcessing Instruction
  • DocumentTypeとProcessingInstructionはまず使わないでしょう

  • ちなみに、従来は複数の種類のノードに存在すべきメソッドは全部nodeに定義されていました。

  • 互換性の問題から、appendchildといった旧来のメソッドをいきなり消すことはできません。そこで、parentnodeにしかない新しいメソッドを導入することにしたのです。appendchildは依然として存在し続けますが、それでも新しいメソッドを作ることに意味はあります。というのも、最近はjavascriptの開発環境が充実し、自動補完や(typescriptでは)型チェックなどもできるようになりました。 その精度を向上させることができるでしょう

  • まずはappendです。これは子ノードを追加するメソッドです。さきほどまでさんざん例に出してきたappendchildが進化したメソッドです。

  • 進化したポイントは、まず引数は1つだけではなく任意の数可能です。これにより、複数のノードを一度に追加することができます

  • カンたんな名前なのに、見覚えがないメソッドがあるなと思ってた2022/01/24 1:49
  • もう1つは、テキストノードを挿入したいときはdocument.createtextnodeを使ってテキストノードを作るかわりに、引数に文字列を渡すと勝手にテキストノードに変換してくれる

  • 子ノードを追加するメソッドはもう1つあります。prependです。appendでは親ノードの子の最後に全部追加しますが、prependは最初に追加します。

  • つよそう 2022/01/24 1:53
  • firstElementChildとlastElementChildというプロパティがあります。これは、子ノードでElementであるもののうち最初/最後のものを返します。従来(Nodeのプロパティとして)存在したfirstChildとlastChildは、すべての子ノードのうち最初/最後のノードを返すことになります。

  • のulに対してそのfirstChildはulタグとliタグの間にある改行のテキストノードとなりますが、firstElementChildは最初のli要素になります。正直テキストノードとかどうでもいいという場面も多いので、こちらが役に立つ場面が多いでしょう。

  • めんどくさく罠っぽい 改行テキストノードだ
  • 他に、AllではないquerySelectorというメソッドもあり、こちらはセレクタにマッチする要素のうち最初のひとつのみを返します

  • 他に、queryAllとqueryという似た名前のメソッドがあります。こちらはセレクタではなく相対セレクタ(> pみたいな)にマッチする要素を返します。

  • まず、最初のメソッドはremoveです。これは引数なしのメソッドで、親ノードから自身を取り除きます。

  • replaceWithです。これは親のreplaceChildを呼ぶのに相当するメソッドで、引数に渡されたノードで自身を置き換えます。先ほど紹介したappendやprependと同様に、複数のノードや文字列を引数に渡すことができます。

  • beforeとafterメソッドがあります。これは、自分の前または後に、兄弟として引数のノードを追加する

  • プロパティとして、previousElementSiblingとnextElementSiblingがあります。previousElementSiblingは、自身の兄弟ノードで、自身より前にあってElementであるもののうち最初のもの(一番自身に近いもの)を返します。

  • 今回はDOM4時代の基本的なメソッドをいくつか紹介しました。とても便利なメソッドたちですが、現在(2015年5月)まだブラウザの実装がぜんぜん追い付いていない

  • まだ2015/5の情報だった ES2015で大進化したとはいえ長いJS道

よみおわ 2022/01/24 2:05

十七章第三回 Custom Elements

https://uhyohyo.net/javascript/17_3.html

8100字

  • Web Components
  • 名前だけkiitakotoann
  • ウェブページの構築に使える再利用可能なパーツ

  • そのための Custom Elements
  • 実は、独自のHTML要素を作るには、HTMLElementを継承したクラスを作ります クラスの構文を使わないとうまくいきません

  • 要素を定義したらそれをカスタム要素として登録する必要があります window.customElementsを用います。このオブジェクトはdefineメソッドを持っており、このメソッドを用いてカスタム要素を登録します

  • window.customElements.define('my-element', MyElement);

  • 要素名はハイフンマイナス(-)を含む必要があります。ハイフンを含むことで、カスタム要素ではない普通のHTML要素と区別することができます。

  • タグ名にはアルファベット以外も使うことができます。"x-日本語??????"などの要素名も可能です。

  • var elm = document.createElement('my-element');

  • jsでしか使えないのかな html に <my-element> と書いて使えないのかな?
  • カスタム要素のインスタンスはdocument.createElementを使わずに、コンストラクタをnewすることでも作ることができます。 document.body.appendChild(new MyElement());

  • <my-element id="elm">
    <p>これはテストです。</p>
    

    </my-element>

  • 書いてもツカエるらしい
  • 既に取得した要素も変化するというのは興味深いというか面白いというかやばい挙動ですね

  • connectedCallbackメソッドは、その要素が文書に挿入されたときに呼び出されます(引数無し)。

  • 僕の知らない関数がたくさんあるね
  • なんか html に <my-element> と書いた後に CustomElementを定義しても、ちゃんと動作する (不思議)
  • 既に文書中に追加されているので即座にconnectedCallbackが呼ばれるという流れになります

  • なるほど
  • static get observedAttributes(){ return ['content']; } とすると この当時でも クラス内にいれれたという感じ

よみおわ 2022/01/24 22:14

十七章第四回 Shadow DOM

https://uhyohyo.net/javascript/17_4.html

  • 3書いくらい続くshadow dom
  • 8000時
  • ここでは、shadowというのは隠されているということを意味しています。 shadow domによりある要素の実装(中身)を隠蔽することができる

  • shadow domを使うには、要素に対してshadowrootを作ります そのためには、elementが持つattachshadowメソッドを呼び出します。

  • 実は、shadowrootが作られるとその中身が要素の中身となり、子要素たちは無視されるのです。

  • shadowrootを用いて要素の中身を作ってやることで、要素の内部構造が外から見えなくなります。これにより、前回述べたような、外から直接要素の中身をいじられて挙動がおかしくなるというようなことを防ぐことができます。

  • 隠したがり屋3
  • 上の例の12行目にあるように、ある要素に対してShadowRootが作られると、その要素のshadowRootプロパティでShadowRootオブジェクトを取得できます。

  • JSでしか shadowRootの中身は維持れ無いのかな?
  • modeが"open"となっているのを"closed"とすると、ShadowRootが隠されます。つまり、shadowRootプロパティを用いて取得できなくなります

  • 実は、ShadowRootを作ったときはattachShadowの返り値としてShadowRootが得られる

  • 自分はそれを使って維持れる

2022/01/25 22:26 - shadowrootの下にある隠された木構造のことをshadow tree(shadowツリー)といいます - > shadow domの便利さを説明していきます。。。実は、shadowツリーはcssに関して特殊な扱いを受けます。簡単に言うと、shadowツリーの中身は外のスタイル定義の影響を受けません。中のスタイル定義は外に影響を与えません。 - スタイル定義の影響はうけないけど、スタイルけいしょうの影響はうける - > style="color: initial" - これでキャンセルしよう

読了 2022/01/25 23:09 

十七章第五回 Shadow DOM 2

https://uhyohyo.net/javascript/17_5.html

8500じ

  • HTML5のtemplate要素 template要素は、別のところで使いたいHTMLの断片をあらかじめ書いておくことができる要素です。 template>

  • innerHTMLの場合はデータが文字列なので、innerHTMLにそれが代入されるとまずは文字列をHTMLとして解析してDOMの木構造を作る必要があります。対して、template要素の中身は既に解析されており、木構造として保持されています 高速に行うことができる

  • template要素とCustom Elements, Shadow DOMの組み合わせ方です。今後はこれを使っていきましょう。

  • 定番の組合せらしい
  • スロットは、shadowツリーの中にslot要素を配置することにより作ります

  • shadowツリーの中にスロットを配置することで、本来の(shadowツリーではない方の)子要素をスロットの位置に配置することができます

  • <my-element> の中身が template> の中の の中にあらわれるらしい
  • ちなみに、shadowツリーではない本来の子孫たちのことは、shadowツリーと対比してlightツリーと呼ばれます

  • slotは複数おけるとのこと
  • デフォルトスロットとは、name属性により名前が付けられていないスロットです。 同じスロットに複数の要素を入れることができます

  • slot="title" なものが name="title"なslotに入る

よみおわ 2022/01/27 0:19

十七章第六回 Shadow DOM 3

https://uhyohyo.net/javascript/17_6.html

2500時

  • Shadow DOMとイベント shadowツリーの中で発生したイベントはどうなるのでしょうか。 shadowツリーの中で発生したイベントがshadowツリーの外に出た場合、shadowホストが発生源であるように偽装される

  • カスタム要素を使う側はその内部構造を知らなくても要素を使えないといけないのです。

  • shadow domは、カスタム要素を作るときには必須といえるほど便利

十七章第七回 HTML Imports

https://uhyohyo.net/javascript/17_7.html

6500時

  • 今回紹介するのが最後のひとつ、HTML Imports 読み込むのはjavascriptファイルではなくhtml文書

  • 他のhtml文書を読み込むためにやはりlink要素を使います link要素のrel属性を"import"にすることにより、他のhtml文書を読み込むことを示すことができます。

  • 読み込んだHTML文書はJavaScriptから見ることができます。そのためには、link要素のノード(HTMLLinkElement)が持つプロパティimportを参照します。これは、読みこまれた文書を表すDocumentオブジェクトです。

  • ところで、link要素によって読みこまれた文書中にスクリプトがあった場合はどうなるでしょうか。実は、その場合そのスクリプトはちゃんと実行されます 読みこまれる文書内で作られた関数fooを読み込む側の文書で使うことができています

  • 読みこまれる側でもdocumentというグローバル変数が読み込む側の文書を指している

  • 読み込む側の文書となるなら、読みこまれる側の文書を得るにはどうすればよいのでしょうか。それには、document.currentScript.ownerDocumentとします。ownerDocumentは以前紹介しましたね。そのノードが属するDocumentを示すプロパティです。

  • 今まで解説したことを利用すると、カスタム要素の定義を別の文書に独立させることができます。

  • なるほど。この技術、jsの実際の世界で使われてるのかな? 2022/01/28 0:26
  • 今回は全体が無名関数に囲まれています(20?39行目)。この目的は、変数tmpやMyElementクラスを関数の中のローカル変数としてしまうことで外から隠蔽することです

  • template要素はhtmlの概念なので、javascriptファイルだけでなくhtml文書の形で読み込めるようにする必要があったのです。これを可能にしてくれるのがhtml importsというわけですね

  • 特に、類似した機能を持つes modulesが先に安定したためes modulesのほうに注目が集まっているようです。

ヨミオワ 2022/01/28 0:33 あと行っかい!

質問と回答1

https://uhyohyo.net/javascript/qa1.html

3700時

  • String#matchの返り値の配列にはもうひとつinputというプロパティがあり、これは検索対象の文字列全体です。

  • var regexp= /090-(\d{4})-(\d{4})/g;

  • regexp.exec() すると、lastIndexをつかってうまいこと鄒プできる

JavaScript中級者になろう 16章(後半)を読んだ (ES2015-17)

前: JavaScript中級者になろう 16章(前半)を読んだ (ES2015) - t_hazawaの日記

概要

  • ES2015(-17) を知った
  • ES2018~2022 も何が増えたか項目は見た
  • この↓ 24600字ある

十六章第十一回 クラス

https://uhyohyo.net/javascript/16_11.html

  • 目玉機能
  • これで、継承さんしゅるいめかな かきかた多い
  • JavaScriptにおけるクラスは、端的にいえばコンストラクタを作る新しい方法

  • class Foo{ constructor(arg){ this.prop = arg; } }

  • いままでもnew 演算子アったよね コンストラクタがあればnew 使えるのかな
  • ただし、JavaScriptにおいてクラスという概念は本来存在しません その実体は関数(コンストラクタ)です。実際、typeof演算子を使って調べるとtypeof Foo === "function"となる “クラス”は関数

  • なるほど classがふえたわけではないのね
  • クラスとして作られた関数はコンストラクタ専用なので、newをつけずに呼び出すことはできません 関数の役割の明文化の一環

  • constructorという名前の関数は特別扱いとなり、この関数の処理がコンストラクタの処理となります

  • 昔の方法では、メソッドはprototypeを用いて定義しました。クラスの構文を使うともっと楽に定義することができます。

  • どっちのやり方出作ってもできるものは同じっぽい(?)
  • なんだか懐かしいサンプル

  • attackメソッドの実体はTeki.prototype.attackにあります。よって、例えばzako.attack === Teki.prototype.attackはtrueになります クラス宣言は我々が第九章で四苦八苦したことを簡単にやってくれる便利な構文

  • なるほど。便利になっただけだった。これからは必ずこの構文で書かれることだろう(こっちに寄せるのが良さそう)
  • クラス宣言の中でメソッドを定義するときは、定義の前にstaticと書くことによりstatic関数を定義することができます。 staticが付いた定義はTeki.prototypeではなくTekiのメソッドとして定義されます。

  • さっそく新キャラ登場
  • staticな定義はインスタンスのメソッドを定義するのではなく、コンストラクタにくっついたメソッドを定義します の機能は、コンストラクタのメソッド(例えばArray.fromとか)を作りたいときに役に立ちます。

  • なんか自分の他言語でしってるstaticかんすうとちがうきがする
  • 言語によってはクラスに「privateメソッド」とかいう機能が備わっていますが、それはありません。(ただし、クラス宣言におけるプロパティ定義構文がStage 3、privateメソッド/プロパティはStage 2ですので(2017年10月現在)、ES2018くらいにこれらの機能が追加されるかもしれません。)

  • いまも正式な機能としてはなさそう がんばっをユーザがつくってる
  • クラス宣言は任意のブロックの中に書くことができます。このとき、それにより定義されたクラスはそのブロックをスコープとして持ちます。

  • クラスの定義はこのようにconstructor関数を省略することができます。その場合、コンストラクタは何もしない関数になります。

  • クラス式もあります。クラス名を省略できます。

  • var Foo = class { hello(){ console.log("Hi!"); } };

  • むめいくらすだ
  • コンストラクタは関数なので、返り値を返すこともできます。この場合、実はnewでインスタンスを作った結果がその返り値の値になります。

  • 本当にただの配列であり、Fooのインスタンスではありません。こうなるとFooクラスを作った意味があまり無いような気がします。

  • クラスの構文は分かりやすく便利なので、オブジェクト指向的なことをするときはぜひ使っていきましょう。

よみおわ 2022/01/02 23:54 18m

2022/01/06 10:58 0m 再開

十六章第十二回 クラスの継承

https://uhyohyo.net/javascript/16_12.html

  • いままで行っていた継承をカンンンにできるらしい
  • class Dragon extends Teki{

  • おなじみの構文
  • もはや全てこっちの構文で書かれるのだろう
  • これの裏では、以前解説したprototypeチェーンがちゃんとあります コンストラクタの継承も自動

  • class Foo extends (class {}){}

  • むめいクラスのKE化粧も可能
  • 継承を行った場合、実は静的プロパティ,静的メソッドも継承されます。

  • super呼び出し

  • Dragonのコンストラクタがあるときに親のTekiのコンストラクタを呼びたいときとかに  super(name, hp);
  • クラス構文を使って継承する場合、子のコンストラクタ内で親クラスのコンストラクタを必ず呼ばなければいけない

  • 一般にコンストラクタではthisのプロパティに代入するなどしてオブジェクトの初期化を行いますが、super呼び出しはthisを触る前である必要があります(thisに全く触らないでもsuperは呼び出す必要があります)

  • super.メソッド名とすると、親クラスのメソッドを得ることができます(super[文字列]の形でもいいです)

  • なんか、 super という名前の変数は作れなさそうだね 予約後が増えてそう
  • クラスの機能はこれで全てです。今までのjavascriptらしからぬ文法ですがとても便利

  • new.target
  • new.targetは関数の中で使うことができ、newで呼ばれたときはそのときのコンストラクタが入っています

  • メタプロパティという言葉はfunction.sentの話のときにちらっとでてきました

  • ひとつの使い方は、関数がnewで呼ばれたのかそうでないのかを判別すること

  • 小クラスがなにかを親くらすのコンストラクタが知れるとのこと

yomiowa 23m

十六章第十三回 MapとSet

https://uhyohyo.net/javascript/16_13.html

  • 謎のset でもdomら辺で出てきたヤツかな
  • Es2015の新文法はほぼおわったらしい
  • ここからは新しい組み込みオブジェクト
  • ◎setとaddの違いか セットはキーがなさそう
  • Setもキーはあるらしい
  • >Map・Setではキーにたいして任意の値を使うことができます
  • >mapやsetのキーとして使う場合はnanどうしは同じ値と見なされます。
  • >今中に何が入っているかという情報が使える
  • Weakはいまどんなキーが使われてるか参照できないなう(2022/01/08 11:52:52)
  • やっぱりsetはキー無しのようだ https://ja.javascript.info/map-set なう(2022/01/08 11:55:06)

ここまで10.5ふん

  • イテラブルを引数にコンストはくとできるマップ
  • 便利なnew Map(arr.entries());
  • Foreach よりfor-ofの方がナウいらしいなう(2022/01/08 12:20:49)
  • Map.@@iteratorがあるので、for-ofでmap自体をしていできるなう(2022/01/08 12:23:48)

17.5ふんなう(2022/01/08 12:24:25) なう(2022/01/08 19:37:48)

  • >先ほど、[キー, 値]がMapの基本単位だと述べましたが、Setの場合は値が入っているかどうかという情報しかないので、値そのものが基本単位となります。

2022/01/08 22:21

  • console.log(s); // Set {"foo", "bar", 3}

  • なんか、こんなふうに表されるらしい
  • console.log(s.has('foo')); // true

  • valuesメソッドが存在し、これはSetに入っている値をひとつずつ取り出すイテレータを返します

  • entries() や keys() もあるとのこと
  • もちろん set.@@iterator があるので s 自体がイテレータ
  • .forEach() もあるぞ

2022/01/08 22:25 24m yomiowa

十六章第十四回 Proxy

https://uhyohyo.net/javascript/16_14.html

  • 驚異の14000時 一つ前は4400時
  • proxyを紹介します。これはes2015の新しい機能で、動作をカスタマイズしたオブジェクトを作成できる

  • set(), get() の進化系らしい
  • var obj = new Proxy(target, { get(target, name, receiver){ return name; }, });

  • 引数は2つで、第1引数(今回はtarget)はカスタマイズされるオブジェクトです。

  • 第2引数はトラップ (trap)を定義するオブジェクトです。各トラップは関数であり、今回はgetというトラップのみ定義されていることになります

  • Proxy を介して、 target を操作できるらしい
  • ゲッタは各プロパティに対して設定されるもので、そのプロパティに対するアクセスが関数によりカスタマイズできる

  • Proxy の getトラップでは、全プロパティへのアクセスを一律でカスタマイズデキるとのこと
  • 役に立つ例としてよく紹介されるのがデフォルト値を持つオブジェクトです

  • setトラップもあります。 例えば、値は数値しか許さないという厳しいオブジェクト

  • これはプロパティの値をただ返すのではなく100倍にして返すという見えっ張りなオブジェクトです。

  • 最後のほうの例ではvar target = {};とせずにProxyの第1引数に新しく作ったオブジェクト{}を直接渡しています。こうすることでもとのオブジェクトを隠蔽でき、トラップを介さない操作を防ぐことができるでしょう。

  • 他にも愉快なトラップがいくつもあります。まずはhasトラップ in演算子の挙動に影響を与える あるプロパティがあるオブジェクトの中に存在するかどうか調べる演算子

  • in演算子しか詐称することができません hasOwnPropertyに対しては無力

  • configurable は プロパティごとの属性で、 拡張不可はオブジェクトの属性なのね
  • proxyといえどもオブジェクトのプロパティに関する諸々を詐称するのは大変

  • ownKeys トラップで、キー一覧とかを詐称できる
  • getやsetはまぁ使い所が分かった感じ
  • 制限が色々と多い
  • 一覧の順番を変えたりできる
  • definePropertyトラップがfalseを返した場合はObject.definePropertyはエラーを発生させます。

33分 7割読んだ 次は まず、拡張不可能オブジェクトに対して

  • propertyのdeleteをトラップもデキる 2022/01/10 23:39
  • prototype を Array.prototype と詐称したりもできる
  • Object.setPrototypeOfは紹介していませんでしたね。これはES2015で追加されたメソッドで、その名が示す通りObject.getPrototypeOfの逆で、あるオブジェクトに対応するprototypeオブジェクトを変更できるメソッド このメソッドは気軽に使うべきではありません。本当に必要な場面でのみ使いましょう

  • 詐称どころか、prototype を変更もできる
  • prototype だとそういうことができるのだなあ
  • apply で 関数オブジェクトを関数として呼び出せる
  • function#applyというのはfunctionのインスタンスが持つapplyメソッド

  • apply トラップをツケると、applyでの呼び出しに処理を追加できる
  • クラスは関数ですがnewを用いた呼び出ししかできない

  • construct トラップすると、インスタンスを作らせなくしたりできる
  • Proxy.revocable でも Proxyを作れるらしい2022/01/11 0:00 18m
  • 返り値は、proxyとrevokeという2つのプロパティを持ったオブジェクト

  • revoke すると、そのproxyは使えなくなる
  • 何らかのトラップが介入できる操作はこのように全てエラーとなります。 トラップの情報を捨てる目的は主にメモリの節約

  • proxyオブジェクトそのものは必要だけどもう操作しないという稀有な状況が発生しそうで、しかもメモリを節約したいという状況なら使いみちがあるかもしれません。

  • Proxyに関係深い Reflect というのがあるらしい

2022/01/11 0:03 22m よみおわ 長かった

十六章第十五回 Reflect

https://uhyohyo.net/javascript/16_15.html

  • Reflectは組み込みオブジェクト これらのメソッドはオブジェクトの操作に利用することができます

  • reflectに存在するメソッドはproxyのトラップと一対一で対応しています

  • // obj.foo と同じ意味 console.log(Reflect.get(obj, 'foo', obj));

  • 1つめの引数と3つ目の引数は同じものを渡す…?
  • reflectのメソッドの特徴は、エラーを発生させない

  • Object.definePropertyの場合はエラーとなります。一方、Reflect.definePropertyを使うとエラーが発生せず、失敗を表すfalseが返り値として返ってきます。

  • なんか、オブジェクトをエラーを発生させずに触るものっぽい?
  • Reflectのメソッドは失敗してもエラーを発生させたくない場合に適しています。また、明らかにProxyとよく対応していることから、Proxyと一緒に使われることがあります

  • このようにトラップから「本来の動作」を行いたいという場面は結構あります。。。このような場合にreflectのメソッドを使うと綺麗に書くことができます。 reflectのメソッドに渡す引数はトラップに渡された引数と対応しているので、次のようにできます。

  •   return Reflect.get(target, name, receiver);
    
  • とかけるらしいけど、そんなにメリット感じないぞ…?
  • receiverはゲッタセッタ内でthisになるべきオブジェクト
  • 第3引数を省略できます(省略すると第1引数と同じになります)

  • Reflect というものがあるのはわかった

十六章第十六回 ES2015以降の配列

https://uhyohyo.net/javascript/16_16.html

13500 字 ながい

  • es2015では例によって、配列に新しい機能(メソッド)が追加されました

  • イテレータ系メソッド。 -> fillメソッドは、配列の要素をまとめて変更できる便利なメソッド

  • 追加された配列系メソッドの紹介回みたい
  • 第2引数と第3引数で指定された範囲の要素を全て第1引数の値にします。ただし、引数で示される範囲は第2引数(開始位置)の位置から第3引数(終了位置)の直前まで

  • 今まではこのようなことを行いたい場合はループを回すしかなかったので、簡単にできるようになったのは嬉しいですね

  • -1は最後の要素、-2はその一つ前の要素を指します。配列の最初から、最後の1つを残して全て書き換えたい場合はarr.fill(100,0,-1)とできます

  • 第3引数を省略すると配列の最後まで書き換えられるのは便利です。第2引数と第3引数を両方省略した場合は配列を全部書き換えることになります

  • var arr=new Array(100);。arr.fill(0,0,100);

  • Arrayのコンストラクタは長さなのね
  • copyWithinメソッドは、配列の要素をまとめてコピーできるメソッド 同じ配列の中である場所から別の場所にコピーする

  • 第2引数(開始位置)から第3引数(終了位置)までの要素を、第1引数(コピー対象位置)の位置にコピーします

  • コピー先は上書きされるとのこと
  • c言語を知っている方は標準ライブラリのmemmove関数を思い出すかもしれません。特にtypedarrayの場合(後述)はそれくらいのパフォーマンスが場合によっては期待できるでしょう。

  • 次に紹介するfindとfindIndexは検索系の便利なメソッド これらのメソッドはindexOfが進化したメソッドです

  • indexOfは第1引数に検索する値を渡しましたが、findやfindIndexでは関数が渡されます。

  • true(または真偽値に変換するとtrueになる値)を返す値を見つけたらその値が返されます findIndexは位置

  • 第1引数は判定対象の要素で、第2引数はそのインデックス、第3引数は配列そのもの

  • includesメソッドは非常に単純です。与えられた値が配列に含まれるならtrue、含まれないならfalseを返します。

  • indexOfではnanを検索できない includesでの値の一致判定は===とは異なり、NaN同士の一致を正しく判定してくれます。よって、includesを使えばNaNが含まれているかどうか判定できます。

  • includesが採用している値の一致判定方法は仕様書用語でいえばSameValueZero MapとSetの回でもNaNをキーとして使えるという話題が出ましたが、SameValueZeroはMapやSetで使われている値一致判定方法です。

  • Arrayの静的メソッド

  • Array.ofです。これは、引数を任意の数受け取り、それらを要素とする配列を作って返します

  • コンストラクタは長さだもんね
  • これなら[3,5,7]のように配列リテラルを使えばいいような気がしますね。実際その通りなのですが、関数として欲しい場合にはすこし役に立ちます

  • arrayコンストラクタはもちろん配列を作りますが、その使い方は2種類あります。ひとつは、できる配列の中身を指定する方法です。。。var arr=new Array(3,5,7);

  • 引数が1つのときだけかわるのか…
  • この罠を解消した関数がarray.ofであるとも言えます。

  • ここでemptyという謎の概念が出てきています

  • 実は、このemptyというのはそもそもその位置にプロパティが存在しないということを意味しています。

  • 配列はオブジェクトの一種であり、arr[0]のようにアクセスできる配列の各要素もまたプロパティである arrの0番目の要素は、arrというオブジェクトの0というプロパティなのです

  • 長さの範囲内なのにプロパティが存在しないときにその要素がemptyであると呼びます(正式な名前ではなく、そういう慣習があるというだけですが)

  • 。emptyを含む配列の作り方 から
  • var arr=[0,1,,3,,,6]; console.log(arr);//[0,1,empty,3,empty×2,6]

  • delete演算子でプロパティを消すことでその部分をemptyにするという方法もあります。

  • foreach map は empty むし
  • for-of は empty 無視しない
  • es2015の配列メソッドはemptyに対する扱いが素直

  • 型付き配列。。ところで、配列に似たものとして、file apiの回で型付き配列(typed array)を紹介しましたね。。。型付き配列の定義はes2015からecmascript仕様に取り込まれました。 配列のメソッドはtypedarrayでも使えます。便利ですね。

  • Uint8Array とか
  • 配列の継承について解説します。クラスの回で説明した通り、es2015では継承が楽に行えるようになっています。実は、配列をはじめとする組み込みオブジェクトも継承できるのです

  • 配列を継承してクラスにできるらしい
  • class SuperArray extends Array{

  • Array.ofはそれ自身はそこまで意味がありませんでしたが、継承先でも利用できるのは便利です。

  • filterとかで配列から新しい配列を作っても、元の配列のクラスのインスタンスになる
  • @@speciesです。@@speciesがSymbol.speciesのことである

  • console.log(SuperArray[Symbol.species]); // SuperArray

  • 配列の多くのメソッドはジェネリック性と呼ばれる性質を持ちます。これは、「配列っぽいオブジェクトに対しても動く」 実は配列のメソッドはこのようなオブジェクトがthisとして渡されても動作するようになっています

  • @@isConcatSpreadable

  • concatメソッドは、配列に他の配列をつなげて新しい配列を作ることができるメソッドです。 var arr = [1, 2, 3].concat([4, 5], [6, 7, 8], [9]);

  • var arr = [1, 2, 3].concat([4, 5], 6, 7, [8, 9]);

よみおわ 2022/01/12 23:57 23m

十六章第十七回 ES2015以降のObject

https://uhyohyo.net/javascript/16_17.html

  • 今度はObjectだ
  • サラットトイうけど 6100文字
  • objectの機能というのは、つまりobjectの静的メソッドのことです

  • Object.getOwnPropertySymbolsでした。これはあるオブジェクトが持つプロパティのうち、名前がシンボルであるものを列挙するメソッド

  • マニアック
  • Object.isは、引数を2つ受け取り、その2つが同じならばtrueを返すメソッド プリミティブどうしの比較にも使うことができます

  • object.isによる比較は最も厳密です。よって、後者と同様にnanどうしを比較するとtrueになります。 +0と-0を区別します。

  • もうひとつのゼロ、すなわち-0は、滅多なことでは出現しませんが、浮動小数点数まわりの演算で出現することがあります

  • -0は普通に-0と書くことでも(すなわち、+0にマイナス演算子を付けることでも)得ることができます +0と-0を加算すると+0ですが、-0と-0を加算した場合は-0

  • array#includesの場合(samevaluezero)は+0と-0は等しい

  • 何にせよ、nanどうしが等しいような比較は今までjavascriptで使うことはできませんでした(自分で頑張って実装すれば不可能ではありませんが)。それがこのように簡単に利用できるのはありがたいですね

  • Object.assignです。これは、あるオブジェクトに他のオブジェクトのプロパティを全てコピーして書き込む

  • var obj2 = Object.assign({}, obj1);

  • でコピーするのがよくなる使い方らしい
  • 参照(みたいなもの)を切れるらしい
  • 参照の話もここでされるらしい
  • ここで行われるのは浅いコピー(shallow copy)です。

  • 中で参照してるオブジェクトは同じものを参照するらしい
  • object.assignは「オブジェクトのコピー」に利用されることが多いと思いますが、その実態はあくまでプロパティをひとつずつ新しいオブジェクトに代入しているだけです。

  • ES2017で追加されたObjectの静的メソッドを紹介します。それはObject.entriesとObject.valuesです。 object.valuesやobject.entriesではシンボルをキーとするプロパティは列挙できません。これは、列挙されるプロパティをobject.keysに合わせるためです

  • 要するに、object.keysだけ仲間がいなくてかわいそうなのでentriesとvaluesを仲間に加えてあげたということです

  • console.log(Object.getOwnPropertyDescriptors(obj1)); は列挙不可能でも出る
  • これで皆さんは正真正銘、Objectが持つ静的メソッドを全て知ったことになります。

2022/01/13 0:25 よみおわ 43m

16章はあと 5つ

全体はあと 13

十六章第十八回 ES2015とプリミティブ

https://uhyohyo.net/javascript/16_18.html 2022/01/14 22:23

  • 2進数リテラルと8進数リテラル

  • 2進数リテラルは、0bのあとに0と1を用いて数を記述します。。。console.log(0b1010);//10
  • 大文字を用いて0Bとしても構いません
  • 16進数のxは16進を表すhexadecimalの3文字目です

  • 8進数はoctalなので、0oまたは0oとします。ゼロとオーが紛らわしいような気がしますが、小文字を使えば大丈夫でしょう。

  • なお、昔のjavascriptでは、頭に0oではなく0をつけることで8進数リテラルになる機能がありました。恐らく今のブラウザでも同様の動作をするはずです。この古い8進数リテラルはstrictモードでは禁止されており、文法エラー

  • console.log(2**3);//8 従来はMath.powメソッド

  • この演算子でNaNの0乗を計算すると1になります

  • isFiniteです。Finiteとは、Infinite(無限の)と逆で、有限ということです。この関数は数値の引数を一つとって、InfinityやNaNならfalseを返し、普通の数値ならtrue

  • これらの関数は、es2015ではNumberの静的メソッドとなりました。つまり、Number.isFiniteやNumber.parseIntのように使うということです。ただし、従来の関数を消してしまうと動かないコードが大量にできてしまい困るので、従来のものも使用できます。

  • Number.isInteger()
  • ご存知の通り、javascriptの数値には整数と小数(浮動小数点数)の区別がありません

  • Number.isSafeInteger
  • 絶対値が253-1の整数ではこのようなことは起こらないのです。

  • Number.EPSILONには2.220446049250313e-16が入っています。これは、浮動小数点数の世界で1 + x !== xとなるような(絶対値が)最初のxです。

  • es2015で文字列に関して特筆すべきことは、unicodeサポートの充実です

  • utf-16サロゲートペアにより表される文字(言い方を変えれば、コードポイントu+10000以上を持つ文字、あるいはutf-8で4バイトで表される文字)は、javascriptにおいて2文字として数えられる 絵文字はほとんどが4バイト文字です console.log("??".length);//2 -> 従来のjavascriptは文字の数を数えることすらまともにできなかったのです。非常に残念ですね。そこで、es2015ではu+10000以上の文字もちゃんと扱えるようなメソッドが追加されています。 それはString#codePointAt これはString#charCodeAtの4バイト文字対応版 指定した位置にある文字のコードポイントを返します ??のコードポイントはU+1F602(10進数に直すと128514)

  • "????"という2文字の文字列において、??のコードポイントを取得するには位置として2を指定する必要があります - String.fromCodePoint

  • もうひとつunicode対応が進んでいるのは、文字列をイテレータとして扱った場合です

  • 複数サロゲートペアでも一文字になるとのこと
  • console.log(Array.from("????")); // ["??", "??"] 文字数にちょうど対応した文字の位置指定をしたい場合はこのようにイテレータ経由で配列にしてしまうとよいかもしれません -> "\u{1f602}"のようなエスケープシーケンスです。\u{ }という形の中にUnicodeコードポイントを16進数で記述することで、そのコードポイントの文字となります。従来のユニコードエスケープシーケンスは、"\u28ff"のような形でした。これも同じく\uという形を使いますが、その後ろの16進数は4桁固定です。これはコードポイントではなくコードユニットを表すエスケープシーケンスとなっているので、U+10000以上の文字を表す場合はサロゲートペアを書く必要がありました。新しい方は好きな桁数で書くことができ、コードポイントを用いて文字を表すことができるので簡単ですね。

  • 文字列のメソッドstartsWith, endsWithは、文字列がそれぞれある文字列で始まるか、及びある文字列で終わるかどうかを判定するメソッドです。

  • いままでなかったんだ?
  • console.log(str.startsWith("私は", 6)); // true startsWithは実質指定した位置に指定した文字列があるかどうか判定するメソッドとして利用できます、U+10000以上の文字は2文字として扱います endsWithの第2引数に数値を渡した場合は、文字列のその位置で終わるように指定した文字列があるかどうかを判定してくれます。 文字列strは"田中"の直後がちょうど10文字目

  • console.log("foobar".repeat(5)); // "foobarfoobarfoobarfoobarfoobar"

  • String#indexOfを使えば似たようなことができるのも同じですが、便利で分かりやすいので使えるときは使うとよいでしょう。 console.log("こんにちは。私は田中です。".includes("田中")); // true

  • normalizeメソッドは文字列を指定した方法で正規化するメソッドです。方法は第1引数で指定します。指定できるのは"NFC", "NFD", "NFKC", "NFKD"の4種類の文字列です。 正規化というのはUnicodeの概念です。

  • padStart, padEnd これらのメソッドは、文字列の長さが足りないときに指定した文字で埋めてしまうことができるメソッドです。padStartは文字列の先頭に、padEndは文字列の最後に文字列を付け足します。第2引数は省略することができ、その場合は" "(半角スペース)が補われます。

  • @@toPrimitive

  • オブジェクトが@@toPrimitiveメソッドを持つ場合、そのオブジェクトがプリミティブに変換される場合にそのメソッドが呼ばれます。 以前、オブジェクトがプリミティブに変換される場合に呼ばれるメソッドはtoStringやvalueOfであると説明しました。ES2015で追加された@@toPrimitiveはそれらよりも優先されます。

  • @@toPrimitiveメソッドが呼ばれる場合、第1引数として期待されている型が渡されます。具体的には、"string"、"number"、"default"の3種類の文字列のうちどれかが渡されます

  • var obj = { Symbol.toPrimitive{

  • とすると、obj のこのSymbolをいじれるのだな。。
  • +演算子にオブジェクトが渡された場合、とりあえず指定なし(引数"default")で両辺をプリミティブに変換してみて、どちらかが文字列だったら文字列の連結になるという動作をします。

  • @@toStringTag
  • 普通のオブジェクトを文字列に変換した場合はどんな文字列になるのでしょうか。

  • きになる
  • 普通のオブジェクトは"[object Object]"という文字列になります。また、Promiseを文字列にすると"[object Promise]"となります。 このような変換結果はobject.prototype.tostringメソッドによって生成されます。このメソッドの結果は必ず"[objectなんとか]"という形になります。

  • なんか違う感
  • console.log(String(arr)); // "foo,bar"

  • 便利

読み終 2022/01/15 22:19

十六章第十九回 ES2015の正規表現

https://uhyohyo.net/javascript/16_19.html

2022/01/15 22:19 短そう 2500字

  • es2015の追加機能を網羅しようシリーズは今回で最後です

  • たすかる 2022/01/15 22:23
  • 実は、正規表現も従来はu+10000以上の文字を正しく扱えませんでしたが、es2015では正しく扱う方法が追加されました

  • ということで、今回紹介する新機能はuフラグです。uフラグを持つ正規表現は、U+10000以上の文字も1文字として扱います。

  • yフラグを持つ正規表現は、指定した位置からしかマッチしなくなります。位置は、正規表現オブジェクトの- lastIndexプロパティで指定します。 sticky reg.lastIndex = 3;

  • また、yフラグを持つ正規表現がマッチに成功したとき、lastIndexが書き換えられるという特徴があります。このときlastIndexはマッチした文字列の長さ分だけ進みます。今回の場合、文字列の3文字目から"bar"という3文字にマッチしたので、その分だけlastIndexが進み6となります。

  • 正規表現に関連するwell-knownシンボルは4つもあります。これらのシンボルにより正規表現関連の動作をカスタマイズすることができます。

  • matchメソッドに、正規表現の代わりに@@matchメソッドを持つようなオブジェクトを渡すと、その@@matchメソッドが呼ばれます。他に@@replace, @@search, @@splitというメソッド これらのシンボルは正直、使いみちが全然ありませんが、万一ものすごくカスタマイズした正規表現オブジェクトを作りたくなった場合には役に立つのかもしれません。

  • オブジェクトでもmatch() できるらしい

終わりみじかいい 2022/01/15 22:42

十六章第二十回 モジュール

https://uhyohyo.net/javascript/16_20.html

2022/01/15 22:43

  • 今回は新しい文法を紹介します。それはモジュールに関する文法です。

  • 確かにそういうのもあった(重要そう)
  • 複数のファイルを協調させて動作させる仕組みが必要になります。それがモジュールシステムです。これまではどのようにjavascriptでファイル分割を行っていたのでしょうか

  • この例では、2つのファイルの間の協調はグローバル変数によって成されています。この例ではfoofunctionというグローバル変数が2つのファイルの間の橋渡しをしています。これまでは、事実上グローバル変数を用いるのが唯一の方法でした。

  • 一方、近年はブラウザ以外の環境でもjavascriptが動くようになり、そういった環境用の独自のモジュールシステムが整備されてきた歴史もあります。 その代表例がnode.jsに採用されたcommonjsです。commonjsではrequireという組み込み関数を用いて他のファイルを呼び出し、結果を得ることができます。

  • ◎なるほど require は nodeの commonjsの仕組み

こんかいは 9000字

  • // foo.js exports.fooFunction = function(){ console.log('Hi'); };

// bar.js const { fooFunction, } = require('./foo.js');

fooFunction();

  • モジュールのために、新しい文法import文とexport文が追加されました。import文は、他のモジュール(他のファイル)から値を読み込みます。export文は、自分が他のファイルから読みこまれるときにどんな値を提供するか宣言します。つまり、export文で提供された内容をimport文で読み込むことができるのです。

  • // foo.js export function fooFunction(){ console.log('Hi'); }

// bar.js import { fooFunction, } from 'foo.js';

  • おなじみの記法 2022/01/15 23:26
  • export文にはいくつかの種類があります。

  • しらんかった
  • ジェネレーター関数: yield や next で段階的にすすめられるやつ
  • 他に、var、let、constによる変数宣言にもexportを付けることができます。

  • 意外に少ない 2022/01/15 23:46
  • export let one = 1, two = 2, three = 3;

  • 全部Export
  • 上の例のfoo、barのように、まずexport付きvarで変数を宣言しておき、あとから変数に値を代入することも可能です。この場合、他のファイルがfooやbarを読み込むとちゃんと10、20という値になります。export文を含むファイルもjavascriptプログラムであることは変わりませんので、ちゃんと上から実行されます。

  • 宣言だけExportで、変更しても反映されるのだなあ
  • export class VeryUsefulClass{

  • よくみる
  • export { foo, bar, };

  • なるほど
  • また、エクスポートするときに名前を変えることができます。それには、次のようにasを使います。

  • export { foo as superFoo,

  • はっきりとはしらなかった 2022/01/16 20:30
  • defaultエクスポート

  • 気になる。難しかった記憶
  • defaultエクスポートによりエクスポートされたものは対応するimport構文により簡単にインポートすることができます

  • そのモジュールの中心的なものをdefaultエクスポートにするのがよいでしょう。defaultエクスポートは必ず用意する必要はありません。 変数宣言はだめです。

  • 関数とクラスだけっぽい
  • また、好きな値をdefaultエクスポートにすることができます。

  • let foo=5,bar=10;。。export default foo+bar;。。こうすると15がdefaultエクスポートになります

  • 宣言された後の変数はいいのかな?2022/01/16 20:42
  • なお、defaultエクスポートは1つしか作ることができません。

  • import文の基本的な形は次の形です。 import { foo, bar, } from "./foo.js";

  • 普通はdefault でやるから、この形ではないのね
  • この例では、./foo.jsによりfooとbarがエクスポートされていれば読み込むことができます。

  • エラーがデそうで安全そう
  • さらに、あるモジュールからエクスポートされているものを全部まとめて得るための構文もあります。

  • import * as obj from "./foo.js";
  • これは結構みるかも
  • このように* as 変数名としてインポートした場合、./foo.jsからエクスポートされているものが全てまとまったオブジェクトを得ることができます。例えば、./foo.jsからfooとbarがエクスポートされている場合、それらはobj.fooおよびobj.barに入っています。

  • なるへそ
  • 残りはdefaultエクスポートをインポートするための構文です。これは簡単です。

  • import foo from "./foo.js";
  • console.log(foo);
  • import nanika の書き方はこのdefault のやつだけなのね
  • マニアックなかきかた
  • import obj, { foo, bar, } from "./foo.js";

  • このようにすると、defaultエクスポートがobjに入り、foo, barという名前でエクスポートされているものがfoo, barという変数にそれぞれ入ります。
  • 他に、import obj, * as obj2 from "./foo.js";という構文も可能です。

  • import "./foo.js";

  • これは、モジュールを読み込むけど何もインポートしないという場合に使う構文です。何もインポートしないのにモジュールを読み込む意味があるのかとお思いかもしれませんが、読みこまれると何らかの動作をするというモジュールも考えられます。そういう場合に使うとよいでしょう。
  • 書き方は色々あるけょ、 defaultをつかう import hoge from "hoge.js"; が一番使うんだね
  • export { foo, bar, } from "./foo.js";

  • これはいわゆる再エクスポートの構文です。
  • export * from "./foo.js";

  • また、これは./foo.jsからエクスポートされているものを全て自分のモジュールからエクスポートします。ただし、defaultエクスポートは再エクスポートできません。
  • import文やexport文はモジュールのトップレベルでしか使えません

  • モジュールってなんだっけ
  • モジュールとは、プログラムを分割したそれぞれの単位のこと

  • export とか import したものがモジュールかな?
  • また、特定の条件を満たしたときだけ読み込むとかいうこともできません。もしそのようなことが必要な場合は、条件を満たさない場合は代わりにundefinedをエクスポートするなどの工夫をしましょう

  • 実際にhtmlからこれらの構文を用いてファイルの協調を行う方法をここから見ていきますscript要素のtype属性に"module"という値を指定します。

  • ちなみに、モジュールでないプログラムはスクリプトと呼ぶことになっています。スクリプトでは、importやexportは使えないのです。

  • モジュールとスクリプトがアンんだなあ
  • moduleの中でも、普通に関数を呼べるのね 2022/01/16 23:38
  • 諸事情により、同じディレクトリにファイルがあったとしても、"foo.js"と指定することはできない

  • まず、従来の方法の欠点を解説します。実は、普通のjavascriptがhtml中に現れると、それはパーサーをブロックします。パーサーをブロックするというのは、そのスクリプトの実行が終わるまでhtmlの読み込みが止まるということです。

  • 普通に読み込ませてたらおそいよ ということ 2022/01/17 0:07
  • ただ、html5で追加されたscript要素のdefer属性を使うと、状況は少しよくなります。defer属性を付けたscript要素でスクリプトを読み込む場合、実行は後回しにしてhtmlの読み込みが続行されます そして、htmlの読み込みが終了したあとでスクリプトが実行されます なお、script要素が出た時点でファイル読み込みは開始されます。ファイル読み込みの待ち時間でhtmlの読み込みを進めることができるわけです。

  • src属性を持たないscript要素にdefer属性を付けることはできない

  • defer がないのは即時実行なので、deferで読み込んでるものは使えない、きっと実行時エラーになる
  • 実は、type="module"を指定されたscript要素は、deferと同様に実行が遅延されます これは、たとえsrc属性がなくても有効です。

  • モジュールを使うことで、deferを使うよりも自然にブロックしないスクリプトを書くことができます。これがモジュールの利点です。

  • なるほど?
  • ファイル間のこのような階層的な依存関係を記述できるのはモジュールならではの魅力です。従来の方法では、読み込みたいファイルのscript要素を書き並べるしかありませんでした

  • 近頃実用化が進んでいるhttp2は細かいファイルを同時に何個も受信するのが得意とされており、モジュールによるファイル分割とは相性がよくなっています

  • ただし、注意すべき点は、あるモジュールがどの別のモジュールに依存しているかはファイルを読み込んでみないと分からないという点です。依存関係の階層が深い場合、次々新しい依存先が発覚して結局インターネットを何往復もすることになりかねません。Server Pushを用いるなどの工夫が必要になるでしょう。

  • なるほど push すれば読み込んでさっさなくていいのではやい

よみおわ 2022/01/17 0:39

十六章第二十一回 async/await

https://uhyohyo.net/javascript/16_21.html

2022/01/17 22:33

10500字

  • async/awaitは、またもや新しい文法機能です。これはes2017の目玉機能

  • このasync/awaitを理解すれば、(いくつか解説を省略している機能がありますが)es2017までのおおよそ全ての言語機能が分かったことになります

  • async関数とその中で使えるawait式の2つの要素から成ります async関数は非同期的な処理を記述できる関数 イメージとしては、ジェネレータ関数とyield式の関係に近い感じです

  • async function foo(x){ return x*10; }

  • async関数の返り値は必ずPromiseとなります。

  • foo(5) .then(v=> console.log(v));

  • こうすると50と表示されるはずです。
  • なお、この動作は、返り値の値がPromise.resolve相当の変換によりPromiseに変換されていると見ることができます。 Promiseを返した場合はそのPromiseがそのまま返り値になります。

  • これだけだと返り値がpromiseに変換されるだけで面白くありません。async関数の真髄は、async関数の中でのみ使うことができる構文であるawait式にあります await式はpromiseを受け取り、そのpromiseが解決されるまで待ちます。

  • async function main(){ await waitFor3Seconds(); console.log('done!'); }

  • 時間をかけて実行できる関数なのね
  • await式には任意の式を与えることができます。今回与えた式はwaitfor3seconds()です。waitfor3secondsを呼ぶと、3秒経つと解決されるpromiseを返すので、今回await式に渡されたのはそのpromiseになります。

  • つまり、async関数がawaitによって実行を停止している間にjavascriptは他の処理を進めることができます

  • main関数の実行が終了した場合それでmain関数(が行う非同期処理)が完了したと見なされるため、main関数が返したpromiseが解決されます。

  • promiseの結果はawaitの返り値として得る

  • const y = await double(x);

  • Promiseチェーンで書くより見やすくなるみたい
  • await と Promiseチェーンを組み合わせる場合もあるっぽい 2022/01/17 23:46
  • もちろん whileを含めたりもできる
  • エラー処理のまえまで 2022/01/17 23:48
  • エラーと関わりが深いのが例外です。そうなると、普通の処理における例外が非同期処理におけるpromiseの失敗に対応すると考えるのが自然ではないでしょうか

  • まぁ、 Promise が失敗できるから、 async/await でも失敗できるらしい
  • async関数内で例外が発生した場合、それはその関数が返したpromiseの失敗として現れます

  • async 関数がthrowすると、帰りねのPromiseの失敗としてエられるのね
  • promise を async関数でカエシテもOK(そのPromiseに失敗を登録する)
  • await式で待っているpromiseが失敗したら、その場で例外が投げられます。つまり、await式から例外が発生したような扱いとなります

  • この仕組みにより、async関数を書く場合、大抵の場合はpromiseの失敗を意識する必要がなくなります

  • エラーを制御するには 普通に try-catchできる
  • 非同期処理のエラーをいい感じに処理したいという場面でも、awaitを用いて非同期処理を待つことによって、try-catchを用いて直感的にエラー処理を行うことができます。promiseの場合、catchメソッドを用いてエラー処理を行う必要があるのでどうしてもエラー処理がコールバックの中に入ることになります。

  • const result1 = await double(x).catch(e=> 0);

  • 1行で、しかもconstでかけててすごい
  • このように、async/awaitを基調として使いつつ、ここぞというときにPromiseのメソッドを用いると綺麗で分かりやすいコードを書くことができます。

  • promiseを作る場面があるときはasync/awaitを使って綺麗に書けるか検討してみるのもよいでしょう。

  • async/awaitはあくまでpromise相手に動くものなので、promiseではない古い同期処理(コールバック関数とか)を相手にするのは苦手です。そのようなものをpromise化にするには生のpromiseを扱う必要がある

  • Promiseが増えれば増えるほどasync/awaitも便利になります。皆さんも、非同期処理は積極的にPromiseで書いていくとよいでしょう。

  • 関数式の場合も前にasyncと書くことでasync関数を作ることができます。

  • // 初期値xに対してasync関数fを2回適用する関数 async function runTwice(x, f)

  • 型がないからこういう書き方がデキるのね(何をかかずにfだけ)
  • 関数も引数でわたせるのね
  • async function(x){

  • async x=>{

  • ↑ async関数式
  • 関数を定義する他の方法として、オブジェクトリテラル中で関数を作る省略記法があります

  • async func(){

  • funcという名前の欠んすうなプロパてぃ
  • asyncスコープいなかだけで await ということばは予約される yieldも

yomiowa 2022/01/18 23:14

ついに次タ最後 2022/01/18 23:14

2022/01/19 20:49

十六章第二十二回 TC39とJavaScriptの標準化

https://uhyohyo.net/javascript/16_22.html

短そう 4600ジ

  • なんか ES2015(~2017) の新要素って、目にしたものばかりだったね
    • どういうものかは知らなかったけど
  • Ecma InternationalのTC39は、JavaScript開発者、実装者、専門家などのグループで、JavaScriptの仕様をメンテナンスし発展させるためにコミュニティと協力しています。

  • Ecmaの委員会らしい
  • Ecmaインターナショナル(エクマ・インターナショナル、英語: Ecma International)は情報通信システムの分野における国際的な標準化団体である。以前は欧州電子計算機工業会(英語: European Computer Manufacturers Association、ECMA)という名称であったが、世界的な展開や活動状況を反映して、1994年に現在の名称に改められた

  • 標準化団体はいくつもあります。ECMAScriptを標準化するECMA Internationalのほかに、HTMLやDOMを標準化するWHATWGW3C

  • これらの標準化団体にはgooglemicrosoftmozillaなどのブラウザベンダが実際参画しているため、定められた標準が有効に働き、ブラウザ間での統一が成されているのです。

  • ECMAScriptはその番号を用いてECMA-262と呼ばれることもあります

  • 太古の昔(1995年あたり)、はじめてjavascriptが世に登場しました。それまで動かないhtmlで書かれたページしか無かったウェブに動くページが登場するという大革命です

  • IEJScript
  • 1997年には ECMAScriptになった
  • ここで名前がecmascriptとなったのは、当時javascriptjscriptの2つが主に争っていたので一方の名前を付けられなかったのかもしれません。

  • IEを擁するMicrosoftもいつしかJScriptという看板を捨ててJavaScriptに合流したので、JavaScriptECMAScriptに準拠した唯一の言語となり 実際に我々が書いているのはJavaScriptですが、仕様に関する文脈ではECMAScriptと呼ぶのが主流

  • 一時期ActionScriptという言語がECMAScriptに準拠した形で作られていましたがいつのまにか別物になりました。

  • ES5も確かにバージョンアップだったなあ  そんなにバージョンアップ量多くなかった es5
  • なんか ES2018やES2019が気になってきたぞ…
  • https://qiita.com/ozoneboy/items/9c11ac3323ca94919052
  • なるほど。項目だけはわかった
  • やはり頼れるとほほさん
  • https://www.tohoho-web.com/ex/es2020.html
  • ヌル合体みたことある
  • オプショナル連結(Optional Chaining)(?) も便利
  • インポートしたものを直接エクスポートすることが可能となりました。

  • https://qiita.com/rana_kualu/items/ae3297dd2974fcf047c4
  • Promise.any って ES2021からなのね
  • String.prototype.replaceAll これまでJSには、一致する文字列を全て置換する機能がありませんでした。 実はグローバルフラグを付けると通常のreplaceでも全置換になります。 なので、これまでも正規表現を使えば全置換は可能だったのですが、単純な文字列置換にわざわざ正規表現を持ち出したくはないですよね。

  • a ||= bは、aがtrueっぽい値であればそのままで、falseっぽい値であればbにする、ということになります。

  • JavaScriptのドラスティックな変化ってのはだいたいES2017-2018あたりでやり尽くされたかんじがあり、それ以降は"ちょっとした便利な機能の追加"ってのが多い気がしますね。

  • ES2022
  • https://qiita.com/rana_kualu/items/8bafecd760ae69cfac41
  • 2022という名前にもかかわらず既に一部のブラウザで使用可能、というか一部以外のブラウザで使用可能です。

  • ES2022で class に #privatemethod() ができた #y も 地味に x = 1; とかのpublic fieldも ES2022から? static も
  • 他言語より強力な点として、リフレクションのような手段をもってしてもアクセスすることのできない完全なprivateです。

  • async関数の外側でawaitを使えるようになります。

  • export const hoge = await f(); もできるとのこと

  • asyncでない関数の中では相変わらず使用できません。

  • staticブロックは、クラスが定義された時点で実行されます。引数を渡すことはできません。

  • みたことありそう
  • es2023の話はまだググってもひっかからなかった
  • js中級者に戻る 2022/01/19 21:19
  • ステージ3に上がった提案は、まだ正式にecmascriptの仕様となったわけではありませんが、徐々にブラウザ等に実装され始めます。 実際に実装してみて問題がなさそうなことを確認しないとステージ4には上がれないのです。

  • ステージ3の提案はほぼそのままの形で仕様となる可能性が高いですから、見ておくと予習になります

  • https://github.com/tc39/proposals
  • 皆さんはjavascript自体の言語機能はほぼ網羅してしまいましたが、domを始めとする、ウェブアプリケーションなどを作るのに必要なapiはまだ解説していないことがたくさんあります。今後はそのようなものを解説していきます。

あとはDOMだけ 2022/01/19 21:25 37m

感想

  • ESは 2018以降も普通に進化していってた
  • js中級者は解説の量がとてもしっかりしてたかも(解説がもっと短いものでもよかったかも)

JavaScript中級者になろう 16章(前半)を読んだ (ES2015)

前: JavaScript中級者になろう 15章を読んだ (Web Performance) - t_hazawaの日記

経緯

  • JS力をつけてる
  • ついに、大きくJSが変わった ES2015 (重要で知らないことはだいたいこのエディションっぽい) に到達
  • 22回あるので前後編

# 学習

十六章第一回 WeakMapとWeakSet

https://uhyohyo.net/javascript/16_1.html

  • 全然しらない
  • 今までに説明したes5
  • 今どきはこれくらい分かっていないと中級者とは言えないでしょう

  • 昔は ES6 とよばれてた
  • es2015というのはとても大規模なバージョンアップでしたが、es2016,es2017はそれに比べると小規模です。なので、実質ほとんどes2015の機能であると思っていただいて構いません。

  • ie11は例外です。ieマイクロソフトが開発していたinternet explorerの最終バージョンで、これはes2015にほとんど対応していません 実際の製品でes2015を使いたい場合はこのことに注意しましょう。

  • mapというのはなにかというと、keyに対して値を保存しておけるものです。

  • 今回紹介するweakmapに近いのは、ただのオブジェクトです

  • es2015でシンボルが追加された

  • weakmapでは文字列などではなく、オブジェクトをキーとして使います オブジェクトをキーとして使えるということは、weakmapを使ってオブジェクトに対して別の値を対応付けることができる

  • 2021/12/16 23:42 29m 上まで
  • 2021/12/17 22:22 1m
  • var wm = new WeakMap();

  • 作ったら、setメソッドで新しいキーと値を保存できます。

  • これって実際に使われてるのかな??
  • wm.set(key1, 100); //key1に100を関連付ける

  • wm.get(key1); は 100 をとれるが、 wm.get({}); だと、別のオブジェクトだからだめよ
  • 上の例では、key1に入っているまさにそのオブジェクトでないと100を取り出すことはできません

  • 使いにくそう
  • なお、weakmapでkeyにできるのはオブジェクトのみです。プリミティブをkeyにしようとするとエラーになります。

  • 使いにくそう。(使われてなさそう)
  • 使いみち編 
  • weakmap だと、 GC対象になるのでちゃんといなくなってくれるということらしい
  • 確かにweakだ
  • なるほど。keyにするobjを拘束しないわけね
  • .get(key, default) と第二引数があるよ
  • weakmapが今までに比べて革新的なところは、やはり任意のオブジェクトに対して別の値を関連付けられるということです 配列をはじめとするjavascriptの言語仕様に存在するオブジェクトや、ノードのようなdomオブジェクトが組み込みオブジェクトに該当します。これらに追加情報を関連付けたいときもweakmapは活躍します

  • weakmapはどんなオブジェクトでもkeyとして利用できるので、関数やregexp正規表現オブジェクト)もokです。keyとなるオブジェクトを汚さずに情報を付加できる

  • weakmapならば、それを持っている自分しか値を読んだり書き換えたりすることができず、安全

  • もちろん、WeakMapの中にオブジェクトAをkeyとして保存されていたデータも捨てられます。

  • mapが「キーとなっているオブジェクトの一覧」を返すメソッドなどを持っているため、map内部にしかオブジェクトへの参照が無くなってもそれを外部から取得する手段がある

  • 普通のmapは強いな
  • WeakMap と名前がにてる WeakSet
  • 集合に含まれるかの判定だけできる (getできない)

読み終わりました 2021/12/17 22:41 18m

十六章第二回 イテレータ

https://uhyohyo.net/javascript/16_2.html

  • 使いそう
  • 配列も文字列もイテレータの仲間らしい 正確には iterable
  • for-of文。。for-of文はes2015で新たに追加された構文で、イテレータの中身を1つずつ取り出して処理する文です for文やfor-in文と似た使い方ができます。

  • よくみる
  • var arr=[0,1,2,3,4];。for(var value of arr){。console.log(value);。}

  • 簡単
  • for-of文でもcontinue文やbreak文が使用可能

  • for-of文にiterableが渡されると、それに対応するイテレータが作られ、そのイテレータにより値が順番に取り出される

  • .next()を持つのがイテレータ
  • nextメソッドを備えたオブジェクトならイテレータになります

  • 無限イテレータというのもある
  • イテレータを取り出す方法をもつものが iterable (iterable もユーザが作れる)
  • @@iteratorメソッドなるものを持つオブジェクトがiterableなオブジェクト Symbol.iteratorをプロパティ名とするようなメソッドを作ればよい

  • iterableのfor-of文以外の活用法

  • Array.fromというメソッドがあります。これは、配列ではないものから配列を作るメソッド Object.createみたいに、コンストラクタに直接くっついているメソッド

  • console.log(Array.from("foobar"));。。結果は以下のような配列になります。。。["f","o","o","b","a","r"] 第二引数として関数を指定することができます map操作

  • Array.from("foobar",function(char){ return char.toUpperCase(); }));

  • Array.formはiterableだけでなく、array-likeなオブジェクト(NodeListとか)からも配列を作ることができます。

  • 配列のように利用できるものが array-like
  • Array.from({ "0":"foo", "1":"bar", "2":"baz", length:3 })

  • 配列や文字列などの組み込みのiterableから得られるイテレータはそれ自体iterableになる

  • .entries() でイテレータを得られるらしい
  • このように、iterableから得られるちゃんとしたイテレータは、それ自体がiterableとなっているのが望ましい

読み終 2021/12/17 23:53 35m

十六章第三回 代入

https://uhyohyo.net/javascript/16_3.html

  • 残り 28 書い
  • 代入時にオブジェクトや配列を展開するということが可能になりました

  • var [a, b] = ["foo", "bar"];

  • よくみる
  • destructuring assignment というらしい 分割代入
  • 代入の左辺に配列のように変数を並べたものを置いてやる 余った変数にはundefinedが入ります 右辺の配列のほうが長い場合、余ったところは代入されずに捨てられます。

  • フレキシブル
  • 配列を用いて関数が擬似的に複数の値を返すとか、そういうことも可能ですね

  • オブジェクトっぽい感じの代入も可能です。 var {c, d} = { c:"foo", d:"bar" };

  • オブジェクトっぽいだけで、普通の代入 * 2
  • var {c:foo, d} = { c:"foo", d:"bar" };

  • cでなく fooに入る
  • varがなくても [ は動作する
    • { はブロック分解釈されるので var とか ( がいる
  • ネスト
  • 次の例のように、同じ形のオブジェクトを渡せばそのとおりに値が入ります。。。var[a,b,[c,d]]=[0,1,[2,3]];

  • オブジェクトもできるらしい
  • iterable なら右辺に使えるらしい
  • [a,b,c,d,e]="foobar"; も可能

  • 変数名を書かないことでその部分を飛ばすことができます [a,,b]= [1,2,3];

  • console.log([1,,,2]);

  • としてみれば分かりますが、これは[1,undefined,undefined,2]という配列と同等
  • [a,b,...c] = [1,2,3,4,5]; ...のちからで cは[3,4,5] になる(残り全部) 何も残ってなければ空の配列

  • の応用から次回 2021/12/18 0:00 43m
  • 2021/12/20 22:32 土日は忙しかった 0m
  • for(var [i,val] of arr.entries()){ console.log(i+": "+val); }

  • Array.entries() は なんか、https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Array/entries entries() メソッドは、配列内の各要素に対するキー/値のペアを含む新しい Array イテレーターオブジェクトを返します。 とのこと
  • console.log(iterator1.next().value); // expected output: Array [0, "a"]

  • 配列で [0, "a"] と順にかえしてくれるのね
  • function foo({a, b, c}){

  • foo({ a: 3, b: "bar", c: false });

  • みたいなのもつくれる
  • このように、関数宣言の引数に配列っぽいものやオブジェクトっぽいものを入れてやると、その部分に渡された引数が展開されて入ります。

  • ...の記法を引数にも使うことができます。 引数の最後をこの記法にすると、残りの引数が配列として得られます。 function bar(a,b,...c){

  • console.log(hensuu1, hennsuu2) は変数をスペース区切り文字列連結して出るのね
  • arguments は使われなくなったらしい
  • eS2015では引数の初期値も設定できるようになったぞ
  • なお、引数としてundefinedを渡した場合は引数が渡されなかった扱いになり初期値が適用されます。nullの場合はされません

  • function quux({a,b=3,c} ={}){

  • みたいなのもできる
  • var {a,b=3,c} = obj;

  • もできる(分割代入じのデフォルト)
  • var文は、そのスコープは関数内ということになっています。つまり、関数内ならどこにvar文を書いても関数内全体で通用します(そして、関数の外には影響を与えません)

  • var はどこに書いても、カンすうの最初で初期化されるらしい
  • let はブロック内
  • 厳密には関数宣言の{ }はブロックではありませんが、let宣言の場合はこれも同様に扱います

  • letの場合、明示的に関数の最初というか外にあるブロックのところで宣言しましょうね
  • 基本的に、変数のスコープがブロックに制限されていても困ることはありません。広いスコープが欲しければ、それ相応の位置で宣言すればいいのです。あなたは今let宣言を知ってしまったので、今後varを使う必要はもはや無いでしょう。

  • for文におけるletは特別で、スコープはそのfor文の中になります。すなわち、let i=1;とi<=10とi++というforを構成する各式及び{ console.log(i); }という本体部分にわたってこのiが使用可能です

  • varだと、 for のくりかえし条件で宣言したものをfor分の後でも使えた
  • if文などがなくてもブロックを作ることができます。

  • 何もともなわずに { } とかける
  • 本来if文やfor文などは処理部分を1文しか書くことができません。その1文にブロックを当てはめることで複数の文を処理させているのです。

  • constもスコープはlet とおなじ 。 ブロックスコープ
  • const宣言にはある変数が定数であると分かりやすくする効果があります。

  • strictもーどでない場合は、代入しても何も起きない
  • オブジェクトをconstで宣言してもオブジェクトの中身は変わる可能性がある constはあくまで変数への代入(obj = なんとか)を制限するのみで、変数に対するその他の操作は一切制限されないのです。

  • constは宣言時に必ず代入がいる
  • 必要がないのに再代入可能なのはバグの元なので、再代入する気がない変数はconstで宣言しましょう。そうすると、ものにもよりますが、プログラムの変数宣言の9割くらいはconstになります

  • 変数の再宣言ができないということです。。。実は、varでは同じ変数を何回も宣言することができました

  • 2回目以降のvarは無視される。単なる代入になる感じ

読み終 2021/12/20 23:01 22m

十六章第四回 シンボル

https://uhyohyo.net/javascript/16_4.html

  • 新しいプリミティブであるシンボル
  • シンボルは既存のプリミティブとは違い、リテラルによる表現を持ちません シンボルを作るには、Symbolという組み込み関数を呼び出します。 - - let s = Symbol();

  • シンボルは、オブジェクトのプロパティのキー(プロパティ名)にすることができます。今までオブジェクトのプロパティ名は必ず文字列でした。

  • String関数は渡されたものを文字列に変換する関数

  • なお、複数回symbol()を呼び出すと、毎回異なるシンボルが返されます

  • かならず違うキーをシンボルでつくれるのだ
  • Object.keysやObject.getOwnPropertyNames は文字列キーしか列挙しないので、シンボルキーは見つからない
  • Object.getOwnPropertySymbols でみつけてね
  • javascriptをバージョンアップするにあたって既存の機能を変更・追加したときに既存のes5プログラムが壊れたら困るので、es5プログラムからは見えないシンボルを使って機能拡張を行った

  • well-known symbols
  • Symbolのプロパティとして参照可能 主に 組み込み関数の動作をカスタマイズするために使う

  • 2021/12/20 23:10 言っっんおわり 30m
  • 次はイテレータから 16_4
  • イテレータの話で@@iteratorメソッドなるものを紹介しましたが、実はその実体はこのwell-known symbolです @@iteratorというのはSymbol.iteratorのことです。なんということはありません。プロパティ名がwell-known symbolときにいちいちSymbol.iteratorと書くのは大変なので代わりに@@iteratorと書いている

  • Synbol. を @@ とかけるらしい
  • つまり結局のところ、iterableなメソッドは、Symbol.iteratorをキーとして参照できるメソッドを持てばいいのです

  • iterable を作るには Synbol.iterator にいい感じのfunctionを入れればいいらしい
  • 本来は、データはiterableの中にあって、イテレータはそのデータを参照して順番に返す仕事をするだけでなければなりません。この例はiterableではなくイテレータがデータを持っているからだめですね。

  • [ ]で囲むことで、オブジェクトリテラル中のプロパティ名を式にできます

  • シンボルキーのオブジェクトプロパティをtukunnのに便利
  • また、実はSymbolには第1引数として文字列を渡すことができます。これはそのシンボルの名前、あるいは説明を指定するものです。

  • var a=Symbol.for("foo");

  • なんか、文字列に対応したSymbolが作れるらい Symbol.keyFor

yomiowa 2021/12/21 22:34 17m

十六章第五回 Promise

https://uhyohyo.net/javascript/16_5.html

  • お待ちかね
  • 11000文字
  • ES2015(ES6)からだったのね
  • Promiseは、簡単にいうと非同期処理を抽象化したオブジェクト

  • いままではイベントに登録して非同期処理をしていたのだ
  • このサイトで多く紹介してきたdomがもともとイベントをベースにした設計になっており、多くの非同期処理的apiがその延長上のものとして定められてきた

  • 非同期処理の他の方式としては、コールバックを渡すというものがあります

  • node.js の fsモジュールでもコールバックを使うらしい
  • fs.readFile("ファイル名",{encoding:"utf8"},function(err,data){ console.log(data); });

  • 非同期処理には複数のパターンがある

  • JSの難しいところ(複数の書き方がある)
  • Promiseにより、非同期処理に関する処理を書きやすくなります promiseを使った非同期処理を行う関数は、コールバックを受け取ったりする代わりにpromiseオブジェクトを返します。

  • const p = readFile("ファイル名"); p.then(function(data){ // ... });

  • みたいにかけるようになる 確かにネストが減ってそう
  • promiseオブジェクトを得たら、やはりコールバックを登録する必要があります。そこで、promiseはそのためのthenメソッドを持ちます。thenメソッドに対してコールバック関数を渡すと、非同期処理が完了したらその関数が呼ばれます。

  • promiseの結果はコールバック関数の引数として受け取ることができます。

  • 実は、Promiseが表す非同期処理が終了する場合には2種類あります。成功(fulfilled)と失敗(rejected)です。上の例のようのthenにコールバック関数を1つ渡した場合、成功時の処理を登録したことになります。

  • 失敗時の処理も登録するには、thenメソッドに引数を2つ渡します。1つ目の関数が成功時の処理、2つ目の関数が失敗時の処理になります。

  • なんか success: function() {},
  • error: function() {} って書くのはどこだっけ
  • p.then(function(result){ / ここで処理終了時の動作 / },function(err){ / ここでエラー時の動作 / });

  • 引数はいっこっぽい
  • なお、失敗時の処理のみを登録するには、thenの代わりにcatchメソッドを呼び出します。

  • promiseのインスタンスが持つメソッドはthenとcatchの2つです - 思ってたよりシンプル

  • Promise返すメソッドの作り方
  • これもそんなに難しくありません。newでpromiseのインスタンスを作ればよいのです。そのとき、引数として関数を渡します。

  • var p = new Promise(function(fulfill,reject){ });

  • var p = new Promise(function(fulfill,reject){ setTimeout(fulfill,5000); });

  • Promiseの引数のfunctionの中身は即座に実行される
  • fulfill を呼び出すルートが成功ルート
  • Promiseを返す関数に非同期処理を書くのね
  • 複数のpromiseを組み合わせて新しいpromiseを作るためのメソッドがあらかじめ用意されています 「全ての処理が終わるまで待つ」

  • Promise.allメソッド 引数としてpromiseの配列を渡すと、それらが全て成功したら成功となるような新しいpromiseを作って返してくれます。そのときの結果は、各promiseの結果を配列でまとめたもの

  • Promise.race から 2021/12/21 23:19 44m
  • Promise.race()
  • こちらは渡された全てのpromiseが解決するまで待つのではなく、どれか1つが解決した時点で終了するpromiseを返します。なお、解決(resolve)というのはpromiseが成功または失敗することを指します。。。最も早く解決したpromiseが成功した場合、その結果を伴って新しいpromiseも成功します 最も早く解決したpromiseが失敗した場合は新しいpromiseも失敗で終わります

  • 他のpromiseの結果は無視されます(結果が無視されるだけで、非同期処理自体が停止するようなことはありません)

  • 次に、promise.resolveメソッドを紹介します。これは、即座に(ただし非同期的に)成功するpromiseを作って返します そのとき結果の値は、promise.resolveメソッドに渡した値になります

  • なるほど。よく見る気がする
  • Promise.resolve(4)

  • new Promise(function(fulfill,resolve){ fulfill(4); })

  • promise.rejectメソッドもあり、こちらは常に失敗するpromiseを作って返すものです 結果の値はpromise.rejectメソッドに渡した値です

  • このようなpromiseを作る必要があるときに簡単に、また分かりやすく書くことができるので有用です

  • 2021/12/21 23:50 11m 例えばpromiseを返すメソッドを から
  • 例えばPromiseを返すメソッドを作るときに、引数がおかしいのでエラーを出したい場合などは、必ず失敗するPromiseを返すことができます。

  • ちなみに、promise.resolveの引数として別のpromiseを渡した場合は、そのpromiseをそのまま返します。これは、promise.resolveが「値をpromiseに変換する」という役割を持っていると見なせば理解できます

  • 実は、promiseのメソッドthenやcatchは、新しいpromiseを返します。

  • 実はp2は、p1.thenに渡された関数の返り値を結果として成功するようなPromiseになっています

  • メソッドチェーン登場
  • Promise 以外だと、メソッドがなくて難しそうチェーンするのは
  • コールバック地獄の深いネストから開放
  • function doublePromise(value){ return new Promise(

  • みたいにすると、Promise を返す関数がつくれる
  • .then(function(result){ return doublePromise(result); })

  • .then(doublePromise)
  • と書ける
  • 失敗が発生したときにpromiseチェーンがどんな挙動をするのか見ておきましょう

  • 実は、thenのコールバック関数の処理中に例外が発生した場合、そのthenが返したpromiseは失敗します。

  • .then() の引数のfunction は普通の値も Promise も返せるんだなあ
  • p1が失敗したときの振る舞いは指定されていません。この場合はデフォルトの動作をされます。失敗時のデフォルトの動作は以下です。

  • function(err){ throw err; }
  • Promiseチェーンの中で失敗が発生しても、catchすれば成功に戻して続けることができる

  • finally みたいなのもあったっけ?
    • then の第荷引奇数か
  • thenを使うことで、成功と失敗を両方扱うことが可能です。

  • 成功時のデフォルト動作は以下です。

  • function(value){ return value; }
  • 素通りになるるのね
  • 失敗でもデフォルトだと素通り
  • p.then(function(){ / 成功時の処理 / }).catch(function(){ / 失敗時の処理 / });

  • が多いとのこと
  • then() の↓に .catch() もあると、 then() で失敗してもcatchできてうれしい
  • 非同期処理をする関数やライブラリを作るときは、Promiseを返してみるのが今風ということです。

よみおわ 2021/12/22 22:50 18m

十六章第六回 ジェネレータ

https://uhyohyo.net/javascript/16_6.html

  • 2021/12/23 0:17 19m 再開
  • 私の全然知らないことだ
  • 途中で抜けたりまた入ったりできる関数

  • function* で定義して、 yield; で一時停止して、 next();で次に行く感じ
  • g = kansuu(10); みたいにしてオブジェクトにする
  • yield で関数から一旦抜ける
  • なんで generator って名前なの?
  • Generatorオブジェクト
  • 一方、ジェネレータ関数は関数から出たり入ったりできるという特徴があります。

  • yield でも返りねが出せるよ
  • { value: 10, done: false, }

  • の形式で出てくる
  • next(10) にわたして const y = yield; で受け取る感じ
  • ジェネレータオブジェクトはイテレータとしても使える generatorオブジェクトは自身をイテレータとするiterableでもあります 自分自身を返すsymbol.iteratorプロパティを持つ

  • イテレーターとして使ったら、次々にnextするたびに返りね?が生まれるからジェネレーターなのかな

読みおき 2021/12/23 0:28 30m

十六章第七回 ジェネレータ2

https://uhyohyo.net/javascript/16_7.html

  • Generator.return(); がある(強制終了) 帰ってくるvalueもreturnの引数
  • yieldは式中で使えるのに対しreturnは式中に書けない

  • Generator.throw(); は例外をおこす
  • console.log(g.throw(new Error('Hey!'))); // エラー

  • function* gen() { } の中で try catch すればキャッチできる
  • yield*式 渡されたiterable を順繰りにかえしていく
  • 普通に関数式のときも ジェネレーター無名欠かすうを作れる
  • var gen = function(){ yield [1, 2, 3]; };
  • メソッドのときは this もジェネレーター関数で使える
  • ジェネレーター関数はnewで呼べないらしい
  • function.sentはメタプロパティの一種です。メタプロパティとは、プロパティのような構文だけどプロパティではないもの function.sentはジェネレータ関数の中で使えるメタプロパティです。これは、直近のnextメソッドに引数として渡された値

よみおわ 2021/12/23 0:54 44m

十六章第八回 オブジェクトリテラル

https://uhyohyo.net/javascript/16_8.html

  • よく見ると知ってる言葉だった
  • ES2015にはオブジェクトリテラルにも便利な記法が追加されました

  • 一番最後にもこのようにカンマを付けることができます。

  • かなり昔のJavaScriptではできなかったので後方互換性を気にして最後のカンマを付けない人もいましたが、最近はそのような心配をする必要はほぼ無くなりましたので遠慮なく最後のカンマを付けましょう。

  • 数値リテラルを書いた場合はその数値を文字列に変換したものがプロパティ名になります。次のような例に注意してください。 1e5

  • Computed Property Name
  • [式]: 値のようにプロパティ名を[ ]で囲い、その中に式を書きます。式の結果がプロパティ名となります。 [str1 + str2]: 123, プロパティ名を文字列ではなくシンボルにしたい場合にこの記法は必須

  • 変数 foo の中身をもつ 'foo' というキーのプロパティは {foo,} とかけばできる
  • kansuu(foo, bar){}, とすると、 kansuu というキーの関数プロパティができる こうして作られた関数はコンストラクタに利用できない
  • *kansuu(foo, bar){}, ならジェネレーター関数
  • kansuu のところは ''でも1e3でも[Symbol.iterator] でもいける 普通にプロパティのキー
  • 関数オブジェクトはnameというプロパティを持ちます。その名の通り関数の名前 関数式で作った関数は名前がない場合(俗にいう無名関数ですね)もあります

  • シンボルをプロパティ名にした場合は名前無しになります。にもかかわらず、well-known symbolの場合は特殊な名前が付くこともあります。 "[Symbol.iterator]" など

  • 恐ろしいことに、コードポイント記法はプロパティ名や変数名に直に書くことができます。 var foo\u{1d40d}bar

  • 識別子(identifier)はプログラム中に直に書いた変数名などを指す用語です

yomiowa2021/12/24 1:19 11m

十六章第九回 テンプレート文字列

https://uhyohyo.net/javascript/16_9.html

  • 短い 2000時
  • 新しい文字列リテラル

  • console.log(こんにちは、${name}さん); // "こんにちは、山田太郎さん"

  • バッククォートだと ${hensuumei} 展開できるようだね
  • リテラル中で改行してもよいという点です。この改行は文字列中にlf(\n相当)として現れます

  • タグ付きテンプレート文字列
  • 関数 文字列……

  • こうすると、その関数により文字列を加工することができます。
  • ${} 以外の部分が文字列として 配列で第一引数に入る ${} は第似引数以降に入る
  • なんて特殊な形式なんだ
  • タグ付きテンプレート文字列の結果もその通りとなり、文字列でない場合があります。 要するにほとんどただの関数呼び出し

  • もともと用意されているタグ用の関数としてString.rawがあります。これはエスケープシーケンスを処理せずにそのままにした文字列を返す

  • console.log(String.rawfoo\nbar こんに\u28ffちは); // foo\nbar こんに\u28ffちは

  • タグ関数の第一引数には.raw があるラしい
  • ${} は便利とのこと

2021/12/24 1:28 yomiowa 20m

十六章第十回 アロー関数

https://uhyohyo.net/javascript/16_10.html

  • 区切り畳、ここでブログにしたい所存
  • アロー関数式
  • (x, y, z)=>{ ... }
  • function(x,y,z) {} がこう書ける
  • コンストラクタとして使用できない thisを引き継ぐ 関数の外)のthisと同じ コールバック関数を作るときにthisをそのままにしたいときに便利

  • bind が要らなくなる
  • 引数がひとつのときは引数リストの括弧を省略してx=>{ ... }とできます 引数が0個のときは括弧を省略できません。()=>{ ... }とする必要があります。

  • 書き方が色々増えまくった
  • 関数の本体部分がreturn 式;という形のとき、何かの計算をしてその値を返すだけの関数の場合はこれを(...)=> 式と省略できます。

  • var func2 = (x, y)=> x+y; この省略をする場合{}は必ず省略する必要があります

  • console.log(arr.map(x=> x*2)); // [2, 4, 6, 8, 10]

  • 確かにこういう時はとても便利
  • オブジェクトリテラルで作ったオブジェクトを返す関数で上記の省略を使う場合、このように丸括弧で囲まないとうまくいきません。

  • この記法ではfunction式のときのように関数に名前をつけられません。

  • 明確に知らなかったことを知れてよかった

2021/12/24 1:35 27m

感想

  • 最近?でてきたよくわかってない記法が、(js中級者を読み返せば)分かるようになってよかった
  • JSは書き方が複数あって難しいと思う

時間まとめ

  • 2021/12/16-24 (9日間)
  • 10 + 44 + 160 + 20 (ブログ) = 234分
    • 4時間でES2015のことが半分分かったぞ (全部で8時間くらいか?)
  • 累計: 1885分 (=31.4時間)

JavaScript中級者になろう 15章を読んだ (Web Performance)

前: JavaScript中級者になろう 14章を読んだ (データのローカル保存) - t_hazawaの日記

経緯

  • JSちからをつけてる
  • 15章はかなり短かったが、次の16章(ES2015-2017)はとても長いので一旦ブログにする
    • 16章は前半と後半でブログにしたい
  • まったく知らなかった Web Performance。 読んだらわかった

学習

十五章第一回 Page Visibility

https://uhyohyo.net/javascript/15_1.html

  • サクサク動くためのものらしい
  • web performanceはそのような目的で作られた一連の仕様のこと

  • ユーザーが今このタブを見ているか他のタブを見ているか知ることができるもの documentのもつhiddenプロパティ visibilityStateプロパティ

  • 短そう
  • そのページのウィンドウが他のウィンドウに完全に隠されていたり最小化されていたりしたらtrueで、一部分でも見えていたらfalse

  • prerender unloaded(hiddenから別のページに行こうとしてる時)
  • Documentで発生するvisibilitychangeイベント

  • 現在のブラウザの動作を見るに、他のタブを見たりブラウザを最小化すると見えなくなったと判定され、他のウィンドウを上からかぶせただけでは見えなくなったとは認識しないようです。

短かった 2021/12/16 0:07 9m

十五章第二回 Navigation Timing

https://uhyohyo.net/javascript/15_2.html

  • この章は短いのかな
  • navigation timing apiは、ページを表示するときの時間経過とかを知ることができるapi

  • 時間に関する情報を表すPerformanceTimingとその他に関するPerformanceNavigationです。

  • window.performance 。 performance で呼べるぞ
  • PerformanceTimingはさまざまなタイミングを時刻で表すプロパティを持っています。

  • UNIX timeというときはミリ秒ではなく秒数で表すことが多いようですが、JavaScriptではミリ秒とすることのほうが多いです

  • navigationStart 簡単に言えば、このページを開こうとした瞬間です。もうちょっと詳しく言うと、前のページでbeforeunloadイベントの処理が終了したあとunloadイベントが発生する直前の瞬間です。

  • ページ異動するときは、まず前のページで unload イベントが発生するのだなあ
  • fetchStart とかをブラウザが知っテルトイウコトだね
  • ブラウザなので、サーバでは知れないことも知れて新鮮
  • type_navigate みたいな、どういうロード操作かもとれるよ
  • リダイレクト回数もあるよ

2021/12/16 0:21 22m よみおわ

十五章第三回 Performance Timeline

https://uhyohyo.net/javascript/15_3.html

  • PerformanceEntry
  • window.performance に、 このEntry オブジェクトの形でもさっきの(?)情報は入ってるらしい
  • duration とかあるので便利かも 
  • その精度は最大で0.001ミリ秒

  • performance.getEntries() getEntriesByType getEntriesByName

yomiowa 2021/12/16 0:25 26m

十五章第四回 Resource Timing

https://uhyohyo.net/javascript/15_4.html

  • 十五章第二回で紹介したnavigation timingと似ていますね。あちらはページ本体に読み込みにかかった時間であり、本体が読み込み完了してhtmlのパース・domの構築まで終わったら読み込み完了としていたので、外部リソースに読み込みにかかった時間までは測れませんでした。

  • ページから読み込まれた外部リソース一つ一つについてperformanceresourcetimingオブジェクトが作成され、window.performanceに登録されます nameプロパティには、リソースのurlが入っています

2021/12/16 23:12 1m

  • いろんなページで コンソールで console.log(performance.getEntriesByType("resource")); してみよう
  • リソースを読み込む際にサーバー側がTiming-Allow-Originレスポンスヘッダを指定した場合は、他のオリジンであっても時間の情報を取得することができます。

  • マイナーHTTPヘッダー
  • performance.onresourcetimingbufferfull=function(e){ }; とすることによってもイベントハンドラは登録可能

おわり 2021/12/16 23:17 6m

十五章第五回 User Timing

https://uhyohyo.net/javascript/15_5.html

  • 自分で performance オブジェクトにタイミング追加できる マークを登録する
  • performance.mark("mymark");

  • 2つのマーク間の時間を計ることもできるので便利
  • 開始点と終了点はマークの名前を指定しますが、同じ名前で複数のマークが登録されていた場合、最も新しいものが使用されます。

  • ちなみに、measureメソッドの第二引数・第三引数はマーク名ですが、他にもPerformanceTimingのプロパティ名を指定することで、そのタイミングとの差をとることができます。たとえば、

  • performance.measure("test","navigationStart","end");

2021/12/16 23:25 読み終 14m

時間まとめ

  • 2021/12/15,16
  • 30 + 10 + 10(ブログ)= 50分
  • 累計: 1651分