t_hazawaの日記

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

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分

JavaScript中級者になろう 14章を読んだ (データのローカル保存)

前: JavaScript中級者になろう 13章を読んだ (通信) - t_hazawaの日記

経緯

  • JS力をつけていっている

十四章第一回 Storage

https://uhyohyo.net/javascript/14_1.html

  • cookieとの違いは、「データがサーバーへ送られるか送られないか」です storageはサーバー側からは参照できません。javascriptからのみです 基本的にはこちらのほうが便利

  • 一つはlocalStorageであり、もうひとつはsessionStorageです

  • window.localStorage, window.sessionStorage
  • localStorageは同じオリジンなら、違うページからでも同じ内容を共有できる

  • sessionStorageはタブごとにことなる 2021/12/09 0:05
  • 基本は、storageのプロパティに値を入れるとそれがそのまま保存されます。実は、保存できる値は文字列に限ります。オブジェクトとかを保存したい場合はjsonにしましょう

  • localStorage.foo="bar"; localStorage.setItem("foo","bar");

  • getItem もあるが普通にプロパティ参照でいける
  • removeItem
  • clear そのStorageのデータが全て消える
  • length
  • var key=localStorage.key(0); //0番目のキーを取得

  • window.addEventListener("storage",function(e){ },false);

  • Storageに変更があったら window に storage イベントが発生するらしい
  • ev.key ev.oldValue ev.newValue ev.url ev.storageArea
  • 大体は自分で変更したものだろうどイベントがくるんだなあ(?) ←これは違うらしい
  • 共有しているStorage (localStorage)で変更があると、他のタブでイベントがくるらしい
  • clearメソッドの場合は、key,oldvalue,newvalueが全てnullになっています。

  • コンソールで localStorage.clear() してもイベントは飛ばないようだ
  • Storageは expireしないのね (便利)
  • sessionStorage は、一度タブを閉じると1からになってしまいますね
  • sessionStorageには、一時的なデータを入れるといいね (session認証情報ではないね)

十四章第二回 Indexed Database

https://uhyohyo.net/javascript/14_2.html

  • IndexedDBだけで4回ある (使わなさそうだけど、使わなさそうなのはこれだけなのでまぁ全部読んでいいか)
  • 通称IndexedDBは、前回のStorageが進化したようなもの ある種のデータベースをjavascriptから作ってブラウザに保存しておいてもらえる

  • オブジェクト等を保存できる点や検索機能がある

  • ひとつひとつのデータはレコード(record)といい、レコードはkeyとvalueを持つ

  • データベースはオブジェクトストアを保持して、レコードはオブジェクトストアの中に保存される レコードはオブジェクトストアの中に保存されていて、1つ以上のオブジェクトストアをまとめたものがデータベース

  • データベースのなかにオブジェクトストア(MySQLのテーブルみたいなもの?)があるらしい
  • IDBRequestというオブジェクト IndexedDBに対して何か操作を行った時の結果を表すオブジェクト

  • このオブジェクトでsuccess イベントや error イベントが発生する 結果はresultプロパティに入ってる
  • この下位は 8800文字ある 前回は 4900字
  • IDBRequestのreadyStateプロパティ でも終わったかわかるぞ "pending" "done"
  • error, source, transaction プロパティもあるぞ
  • window.indexedDB でアクセス
  • windowのプロパティはグローバル変数でアクセスかのうなので indexedDB でもいける
  • open() がまずいる
  • openはデータベースを開くメソッドですが、そのデータベースが存在しない場合は作ってくれます。つまり、とにかくデータベースを使いたければopenということです。

  • 気軽なJS
  • 引数で指定したバージョンが開こうとしたデータベースより低い場合(すなわち、保存されているデータベースのバージョンが高いのにそれより低いバージョンのデータベースを要求した場合)、このアプリは新しいデータベースに対応していなくて誤動作を起こす可能性があるということなので、エラーを起こしデータベースは開けません。

  • openのバージョン番号を上げればバージョンが上がる
  • バージョン番号は省略可能(うひょさん非推奨)
  • 無事データベースを開けた場合は、IDBOpenDBRequestのresultプロパティには、IDBDatabaseのインスタンスであるオブジェクトが入っています これを用いていよいよデータベースの中身をいじることができます

  • var request = indexedDB.open("test",1); //testというデータベースをバージョン1で開く。openの返り値はIDBOpenDBRequest

  • データベースが処理中で待つ時は blocked イベントが発生する
  • データベースの名前は一度作ったら変えられない

  • close すると多分親切 しなくてもいいのかも?
  • 基本的に一つのアプリケーションなら一つのデータベースで完結するのがよいのではないでしょうか。

  • createObjectStoreの返り値は、IDBObjectStoreというオブジェクト

  • あと39回でおわり (全部で121回 2/3終わってるね)
  • versionchangeトランザクション 実はcreateObjectStoreはversionchangeトランザクション中しか使えないメソッドなので、必然的にこれを使うことになります。

  • バージョン変わるときにしかオブジェクトストアは作成できないのだ
  • versionchangeトランザクションが発動した場合、openの返り値であるIDBOpenDBRequestにおいて、upgradeneededイベントが発生します

  • このイベントの中で createObjectStore とかするらしい
  • db.createObjectStore("foo", { keyPath:"hoge", autoIncrement:true });

  • keyについては次回

十四章第三回 Indexed Database 2

https://uhyohyo.net/javascript/14_3.html

  • オブジェクトストアごとにキージェネレーターを設定できる auto increment
  • 配列、文字列、dateオブジェクト、数値(0以下の数や小数も含む) をキーに使える
  • keyというのは順番に並べることができなければいけません。これは並び替えやインデクシングなどの機能を提供するためです。

  • 異なる種類の値については、大きい方から、配列、文字列、date、数値の順になっています 文字列は文字コード順、Dateは日付順、数値は大きさ順

  • 2つの配列の、0番目、1番目、・・・どうしの要素を比較して、どちらかが大きければ、そちらの配列が大きくなります 長いほうが大きくなります。長さまで同じ場合は配列が完全に同じなので、同じ

  • key の種類が混在しててもOKらしい (フランクなJS)
  • keypathにはkeyのプロパティ名を文字列で指定します 省略すると out-of-line key になる(目に見えないどこか)

  • 自動で key になったりしないのね
  • userid も key にできて便利なのだ
  • "foo.bar"がkeyPath だと、 foo オブジェクトの中の bar がキー 。 柔軟
  • キージェネレータを使うことのメリットは、一意な連番を勝手にレコードに割り振ってくれることです

  • 結構使われるらしい
  • データベースを操作するにはまずトランザクション(transaction)を作ります read でも必要 IDBDatabaseのtransactionメソッド 返り値としてIDBTransactionオブジェクト これがトランザクションを操作するオブジェクト

  • トランザクションをつくるときにオブジェクトストアを指定しないといけないので、joinとかはなさそう
  • トランザクションを "readonly" にしてデータを守ろう というか、複数同時にデータを読めるぞ
  • "readwrite"だと順番待ちになる
  • 第2引数が省略された場合はreadonly

  • 配列を用いて複数のオブジェクトストア名を同時に指定することが可能です。この場合ひとつのトランザクションで複数のオブジェクトストアを同時に扱えます

  • joinありそう
  • abort()で強制的にtransaction失敗
  • IDBObjectStore というオブジェクトを取得してデータを読み書きしよう IDBTransactionのobjectStoreメソッド
  • versionchangeトランザクションはreadwriteトランザクションの上位互換で、データベースへの読み書きが行えるほか、オブジェクトストアを作ったり消したりすることまでできます(

  • データベースに入れることができるものの幅はけっこう広いです。 さらにdateオブジェクトや正規表現オブジェクト、fileやblob、filelist(十二章第五回)やimagedata(これはまだ解説していませんが、canvasを扱うときに出てきます)もokです

  • 以上のものを要素としてもつ配列やオブジェクトもokです

  • 入れることができないのは、関数や、nodeのようなdom関係のオブジェクトです。。。また、オブジェクトについたゲッタやセッタや、enumerableなどのプロパティの属性はコピーされず、デフォルトの状態になる

  • in-line keyの場合には、keyはオブジェクトのプロパティとなります。つまりプリミティブなどはプロパティを持てないのでレコードとしては不適で、エラーになります。

  • 配列はin-line key だとだめよ オブジェクトじゃないから
  • 逆にout-of-line keyの場合には、レコードそのものはkey情報を持たないので、レコードにこれ以上の制限はありません。

  • オブジェクトには代入してもかえられないプロパティがあるよ
  • add, putでれこーど追加
  • 第1引数が追加するレコード、第二引数がそのレコードにつけるkeyです。。。ただし、第2引数のkeyというのは、out-of-line keyのときしか使えません ii

  • キージェネレーターがアッテョ inline-key のときはkeyをレコードにするオブジェクトからしョう略デキる
  • addは重複エラー、putは上書き
  • keyとして正の数値を指定した場合で、かつその値がキージェネレータから発生する次の数値以上の場合、キージェネレータの数値が「その値より大きい最小の整数」に変更されます。

  • 便利
  • オブジェクトストアに対するひとつひとつの操作をリクエストと呼び、その結果を知らせてくれるのがidbrequestです。

  • requestへの結果だけど request
  • IDBRequest.result だからよさそう .error とかあるし
  • idbrequestではイベントが発生する可能性があります。成功したときはsuccessイベント、失敗したときはerrorイベント

  • successイベントは次の処理に進むためによく使いますし、errorイベントは、前述のように、中途半端に失敗したらトランザクションを中断して無効にするというときに、失敗の検出をするために使えます

  • addやputの場合には、idbrequestのresultは追加されたレコードのkey

  • あれもこれも request と名前つけるのはわかりにくそう。。
  • ちなみに、データベースの中身は、Chromeの場合だとDeveloper toolsのApplicationsから見ることが可能です。試しに見てみましょう。

  • あまり使われてるシーンに遭遇しないから実感がない感じ。。

十四章第四回 Indexed Database 3

https://uhyohyo.net/javascript/14_4.html

  • .get() なかったら undefined
  • .delete() resultは特にありません
  • .clear() オブジェクトストアのレコードを全部消す
  • Key Range でまとめて取得や削除ができるぞ
  • key rangeは2つの端点によって定義されます。範囲の中で最小の点と最大の点ですね。 key rangeは、IDBKeyRangeというオブジェクトで表されるのですが、作り方がほんの少し特殊

  • var range=IDBKeyRange.bound(3, 5, true, true); 開いてればtrue 閉じてれば false つまり 3< x < 5

  • 範囲の上限を指定しないkey rangeを作るには、lowerBoundメソッド upperBound only

  • さて、そうして得られたidbkeyrangeには、lower,upper,loweropen,upperopenという4つのプロパティがあります

  • このようにして作ったidbkeyrangeは、keyのかわりにgetやdeleteの引数として使えます。ただし、getにidbkeyrangeを渡しても、レコードが複数得られるわけではありません。当てはまる最初の一つのレコードのみ帰ってきます。一方deleteの場合は、当てはまるレコードを全部消去してくれます。

  • count にこのkey range を渡すとレコード数がかえってくる
  • .getAll とか .gets() みたいなのはなさそう
  • そこで登場するのがカーソル(cursor)です

  • "next" とか "prev" とか動く順番を指定できる
  • "nextunique"。nextと同じですが、重複するkeyをもつレコードは最初のものだけ見ます。。"prevunique"

  • key は重複できたんだ?
  • これは次回の話に関わってきますので、今は深く考える必要はありません。惑わされず、keyは重複しないということは覚えておいてください。

  • 奥深い Indexed DB でも、だいたいサーバにデータを保存するからあまり使われてなさそう
    • まぁ、使わなさ層のは、この講座でこのindexed db が最後だからまぁいいかな(?)
  • openCursorの返り値も、例のごとくIDBRequestです。resultプロパティの値として、カーソルを示すIDBCursorWithValueオブジェクト カーソルが現在いる位置のレコードの内容を示す、keyとvalueというプロパティを持ちます

  • advance(susumu_kazu) 戻れない

  • IDBRequst の success に通知がくるのこと
  • 最後はresult が null になるとのこよ
  • countinue(key_name) そこまですすむ
  • getAll がほしそう
  • updateです。これは、現在の位置のレコードを書き換えるというメソッド key はかえられない deleteもある

  • とても手順が大変な indexeddb

十四章第五回 Indexed Database 4

https://uhyohyo.net/javascript/14_5.html

12600文字

  • id, name, age がある場合
  • そのときには、このオブジェクトストアに対して、新たにageをkeypathとするインデックスを作ってそれを使えばいいのです 実はインデックスは自身のkeypathを持ちます インデックスは基本的に、レコードがオブジェクトでないと効果を発揮しません

  • 複数のインデックスを晴れるのね
  • versionchange トランザクションでしか新インデックスはれないよ
  • IDBObjectStoreのメソッドであるcreateIndex uniqueとmultiEntry

  • multiEntryがtrueになると、検索時の配列の挙動が変わります。配列の要素のうち、どれか一つでも条件を満たせば当てはまるようになるのです

  • deleteIndex
  • IDBIndexのgetとかでレコードを取得してね
  • 実はインデックスのkeyPathには、文字列の他に、複数のkeyPathを並べた配列も許可されています

  • もしインデックスのkeyPathが次のような配列だったとします。

  • ["party","age"]
  • このとき、このインデックスにおけるさっきのレコードのkeyは次の配列になります。
  • ["自民党",72]
  • さらに、範囲指定の例も紹介しておきます。今回の場合、政党名を1つに絞ったうえで年齢の範囲を指定することができます。

  • 範囲指定では使いにくいかもしれませんが、並び替えのためなら配列のkeypathも使い道があるかもしれません。

  • 終了してすることが何も無くなった状態を、イベントループに戻ったなどといいます。この状態になって、なおかつもう処理すべきリクエストが残っていないときが、トランザクションが終了したときです。

  • 複数のカーソルを同時に動かしたりした場合など、どちらが先に終わるのかわからないので面倒です。その場合はcompleteイベントが役に立ちます。。

  • 検索条件として範囲指定しかできませんし、複数の条件を同時に指定するのは難しいです

  • 実際には、スケールにもよりますが、とりあえずkey rangeで一次的に絞り込んで、その後は検索結果に対してif文などで絞り込んでいくことも

  • 操作がめんどそうだった

感想

  • localStorage は使いそうだった
  • IndexedIndexはとても煩雑そうで使いにくそうだった

時間まとめ

  • 2021/12/9-14
  • 10 + 44 + 30 + 30 + 32 + 14(ブログ) = 160分
  • 累計: 1601分 (= 26.7時間)

JavaScript中級者になろう 13章を読んだ (通信)

前: JavaScript中級者になろう 12章を読んだ (HTML5) - t_hazawaの日記

経緯.

  • JS力をつけてる
    • JS知識?

十三章第一回 XMLHTTPRequest

https://uhyohyo.net/javascript/13_1.html

  • 早速13000文字ある
  • Ajaxという言葉はもはや死語かもしれませんが

  • ありとあらゆるところで使われてる、ということかな?
  • Ajaxとは、AsynchronousとJavaScriptに、XMLを組み合わせて作られた造語です。

  • JavaScriptからHTTPリクエストを発行するには、XMLHttpRequestインスタンスを作ります。

  • そして、openメソッドでリクエストを開始します。このとき、パスとメソッドを渡してやります。 connectとtraceはセキュリティの観点から使えないことになっています。

  • ちなみに今回は省略していますが、第3引数は非同期フラグ(後述)で、また必要な場合、第4引数にユーザー名、第5引数にパスワードを渡すことが可能です。

  • 実はopen関数を呼ぶだけだとリクエストは送信されません。リクエストを実際に送信するのがsendメソッドです。。。sendには引数が一つあり、リクエストの本文です。

  • xhrにおいてもイベントを用います。ここで、リクエストが完了して結果が戻ってきたときのイベントはloadです。

  • onloadプロパティを設定するか、addEventListenerでイベントハンドラを登録します。

  • xhr.addEventListener("load",function(ev){ });

  • この時点で、リクエストの結果はxhrオブジェクトのresponseプロパティに入っています。

  • xhr.addEventListener("load",function(ev){ //結果を表示 document.getElementById('result').textContent = xhr.response; });

  • xhrは外で宣言してるから、このイベントリスナーの中でも使えるんだなあ
  • 結果をどんな風に受け取りたいかはXHRオブジェクトのresponseTypeプロパティに文字列を代入してやることで決定します

  • json。結果はjsonで送られてきて、それをパースした結果のオブジェクトを受け取ります。

  • arraybuffer 結果をArrayBufferで受け取ります。この方法ならばバイナリデータも受け取れます。

  • blob 結果をBlobで受け取ります。arraybufferとの違いは、Blobはtypeプロパティ(そのデータのMIMEタイプ)を持っておりこれが使用できるという点です。

  • document HTMLまたはXMLのファイルを受け取ります。結果はパースされてHTMLDocument(送られてきたHTMLファイルに対応するdocument)またはXMLDocument(XML文書の場合)で受け取ります。HTMLになるかXMLになるかは、サーバーから送られてきたデータ(のMIMEタイプ)によって自動的に判定されます。HTMLかXMLかに関わらず、この場合はresponseXMLプロパティでも結果を受け取れます。

  • 詳しくなれた
  • 上の説明でresponseTextとresponseXMLというプロパティが何気なく出現しましたが、これは昔のXHRの名残です。responseプロパティがあれば全て受け取れるので使うことはあまりないでしょうが、昔に書かれたコードに出現することがあります。

  • リクエストヘッダを設定するには、setRequestHeaderメソッドを使います。ただし、タイミングはopenメソッドのあと、sendする前でなければいけません。 xhr.setRequestHeader("Accept-Language","ja;q=0.8, en;q=0.6");

  • ただし、XHRで利用できるヘッダは制限されており、完全に自由にヘッダを操作できるわけではありません。

  • overrideMimeTypeを使ってレスポンスのMIMEタイプを書き換えることでXHRの処理を変えることができる場合があります。html なのに "text/plain" になってる場合とか

  • 次に、statusプロパティを紹介します。こちらは比較的よく使います。これは、帰ってきた結果のhttpステータスコードを数値で得ます

  • 400番台や500番台はページが見つからないなどの問題があったことを示すステータスコードですが、xhr的にはサーバーから何かしら結果が帰ってきたならば「通信成功」とみなされる

  • statusTextプロパティは、ステータスコードに対応するテキストでの説明です。これは各ステータスコードに対して定義されている文字列で、例えば200なら"OK"とか、404なら"Not Found"

  • load以外にもいろんなイベントがあるよ
  • 失敗した場合は原因によって、abort(中断)またはtimeout(タイムアウト)またはerror(その他)イベントが発生します

  • loadendイベントにおいて成功か失敗か見分ける方法としてはstatusプロパティを使う方法があります。通信成功した場合は前述の通り何らかのステータスコードが入っていますが、失敗した場合はstatusの値は0になっています。statusはまだリクエストしていない場合も0なので注意しましょう。

  • ステータスコード204 No Content
  • readystatechangeイベントについてですが、これはXHRオブジェクトのreadyStateというプロパティと関連しています。これは「現在の状態」を表す数値で、以下に列挙します。

  • 0 (UNSENT) まだopenメソッドが呼ばれていない状態。

  • 1 (OPENED) openメソッドが呼ばれたがsendメソッドは呼ばれていない状態。または、sendメソッドが呼ばれたあとまだレスポンスを受信していない状態。
  • 2 (HEADER_RECEIVED) sendが呼ばれた後、HTTPヘッダを全て受信し終えた状態。この状態からstatusプロパティやgetResponseHeaderメソッドなどが利用可能。まだデータ本体は受信していない。
  • 3 (LOADING) 本文のデータを受信中である状態。
  • 4 (DONE) 受信完了したか、リクエストに失敗して終了した状態。
  • 実は昔はこのreadystatechangeイベントしか無かったため、例えばロード完了はloadイベントではなくreadystatechangeイベントを監視してreadyStateが4になったらロード完了だと判断していました。

  • 確かに
  • 例えば。。xhr.timeout=1000;。。としたならば1秒以内に処理を完了できないとタイムアウトで失敗するということです。デフォルトの値は0で、これは無制限(タイムアウトしない)という意味になります。

  • ところで、イベントですから、イベントオブジェクトが存在します。

  • 確かに。存在感ここまでで0
  • ProgressEventという種類のイベントオブジェクト targetプロパティがありますね。この場合、targetはそのXMLHttpRequestオブジェクトになります。

  • 一つ目はloadedです。これは数値で、すでに受信した本文のバイト数です。。。次はtotalです。これは、受信すべきデータサイズの全体です。

  • totalがすでに判明しているかどうかを表すプロパティとしてlengthComputableがあります。これがtrueならば

  • progressイベントは、最短で0.05秒に1回発生することになっています

  • progressイベントと、 ev.total, ev.loaded を使うと進捗表示ができる
  • progress要素という、HTML要素がある
  • https://developer.mozilla.org/ja/docs/Web/HTML/Element/progress
  • XMLHttpRequestUploadです。これはXHRオブジェクトとセットになっていて、uploadプロパティに入っています。

  • クライアントからアップロードする部分のイベントを発生させてくれるとのこと
  • アップロードの進捗ヒョょじもできるとのこと
  • オリジンはホスト名・ポート番号・プロトコルを合わせた概念であり、これが1つでも違う2つのサイトは違うオリジンであると見なされます

  • リクエストを受ける側がhttpレスポンスヘッダによりクロスオリジンリクエストの受け入れを表明する必要があります

  • Access-Control-Allow-Origin: http://example.com http://uhyohyo.net

  • 複数許可はスペース区切り
  • ドメインを列挙する代わりに「*」とすることもできます。

  • 実はXHRオブジェクトにはwithCredentialsというプロパティがあります。これはクロスオリジンのときに関係するプロパティで、falseまたはtrue、デフォルトはfalseです。

  • trueになると何が起こるかというと、CookieとかSSL証明書などの情報も一緒に送られるようになります。これらが必要な場合はwithCredentialsをtrueにしましょう。

  • ただし、注意するのは、このwithCredentialsがtrueの状態で、さらにAccess-Control-Allow-Originが"*"でない場合(ちゃんと列挙してある場合)には、さらに追加のHTTPヘッダが必要になります。 Access-Control-Allow-Credientials: true

  • 実はopenメソッドの第3引数をfalseにすると同期的なリクエストが行われます。

  • この引数は省略するとtrue扱いになるという珍しい引数です。

  • JSではそうなんだ?
  • 現在の仕様では普通のjavascript実行環境ではxhrを同期リクエストで利用することはできません。つまり、第3引数にfalseを指定するとエラーになります。。。こんな意味のない仕様がなぜ存在するかというと、ひとつは歴史的経緯、そしてもうひとつはworkerプロセス内で利用するため

  • 同期リクエストでは、send()が呼び出された時点でブロックされ、リクエストが完了すると戻ってきます。 つまり、send()の直後にresponseプロパティを参照して結果を得ることができます。通信失敗した場合はerrorイベント等の代わりに例外が発生します。

  • バイナリデータを送りたい場合、sendの引数にArrayBufferやBlobを渡すことができます HTMLDocumentやXMLのDocumentを渡すこともできます。そうなると、そのソースを送ってくれます。

  • sendには今回初登場のFormDataオブジェクトを渡すこともできるのです。FormDataをsendに渡すと、HTMLでフォームを送信した場合と同様の本文を生成してくれます。FormDataの第一引数にHTMLFormElementを渡すとその内容を持ったFormDataが得られます。

  • teで作るのは多々変なものを作ってくれるらしい
  • var data = new FormData(); data.append("foo","bar");

  • 第2引数はBlobになります(もちろん、Blobを継承しているFileでもいいということに注意しましょう)。そして、第3引数にファイル名を与えることも可能です。すなわちこんな感じです。

  • //変数blobには何かのBlobが入っている data.append("foo",blob,"file.txt");
  • ファイルも遅れるFromData
  • ちなみに、ずいぶん長い間XMLHttpRequestがHTTP通信を発行する唯一の方法でしたが(Server-sent Eventsを除けば)、最近は新世代のfetchというAPIが登場して取って代わられようとしています。

2021/12/06 21:32 42minで読破した。

310文字/min

十三章第二回 Server-Sent Events

https://uhyohyo.net/javascript/13_2.html

5200字

  • Server-Sent Events (SSE)

  • XHRは“生”のHTTP通信を行うことができます

  • 今回のSSEはXHRに比べてハイレベルなAPIです。SSEで行うことができるHTTP通信の形は決まっていますが、より抽象化された形で通信を扱うことができます SSEを使うとpush型のデータ通信が可能になります

  • push型というのは、「サーバーから能動的にデータを送ってくる」ということです。

  • XHRでは、クライアント発しかできない pollingとか
  • サーバ発の方がリアルタイム
  • sseでは、http通信の範疇でpush型の通信を実現するために次のような方法を用います サーバーはレスポンスを送信中の状態を維持します。そして、サーバーは送りたいデータがあるたびにその接続でデータを送ります。

  • これではクライアントからデータをこの接続で送ることはできないけどね
  • サーバーはtext/event-streamというMIMEタイプでレスポンスを返します。サーバーから送られてくるデータの1単位はイベントといいます。

  • data: foo が1イベント
  • data: foo data: bar
  • これは、「foo(改行)bar」という2行の内容からなる1つのイベントです。
  • 空行くぎり
  • 送られてくるイベントデータの一行一行をフィールドといいます

  • フィールド名:フィールドの中身

  • フィールド名がdataであった場合、そのフィールドは、イベントの内容を表します。

  • event: がイベントの中身
  • イベントの名前はデフォルトである「message」

  • EventSourceというオブジェクトを使います。 var stream= new EventSource("/path/to/source");

  • eventSource.readyState 0(connecting) 1(open) 2(closed)
  • 1がイベント受信可能
  • sseの場合、サーバーからイベントを受信するたびに1回イベントが発生します。イベント名には、eventフィールドを利用して設定されたイベント名がそのまま使用されます。

  • stream.addEventListener("message",function(e){});

  • EventSource は stream という名前の変数になりがちらしい
  • 今回のイベントオブジェクトはMessageEventといいます。イベントの中身は、このdataプロパティに文字列で入っています。他にはoriginというプロパティがあり、これはイベントの配信元のURL(EventSourceの第1引数に指定したURLと同じ)が入っています

  • EventSourceはサーバーから接続が切断された場合再接続を試みる 上のreadyStateの2 (CLOSED)というのは、もう再接続もできず終了してしまったという状態

  • open や error イベントを活用しよう
  • error イベント (再接続しようとする時のイベント)で close する
  • retry:1000。data:hello
  • ミリ秒指定
  • idフィールドでイベントにidをつけられるぞ
  • 再接続時にサーバに教えると続きから送信できるように作れて便利
  • 以上でserver-sent eventsの説明は終了です。まとめると、httpでサーバー側から一方的なpush型の通信が可能だということです。あまり使い所がないかもしれませんが、もし機会があったら使うのもよいでしょう。

  • あまり使わないらしい

2021/12/07 23:57 17m

十三章第三回 Web Messaging

https://uhyohyo.net/javascript/13_3.html

4200文字 どんどん少なくなってく

  • 今回のこれはhttp通信はしません ブラウジングコンテキスト間の通信

  • ブラウザのタブ同士の通信とのこと
  • 自分で作ったブラウジングコンテキストなら知っている

  • window.openメソッドの第一引数はurlです。第二引数はウィンドウの名前です

  • 今回のサンプルはブロックされないブラウザが多いとおもいますが、これは「ボタンをクリックする」というユーザーの動作がトリガーになったせいでしょう。

  • このwindow.openの戻り値はwindowオブジェクトです。このwindowオブジェクトが、その開かれたウィンドウのブラウジングコンテキストを表すオブジェクトです

  • 今開いているページのブラウジングコンテキストに対応するのがおなじみのwindowです 開いたタブについては、そのページに対応するwindowオブジェクトを得ることができる

  • また、今まで慣れ親しんできたdocumentもwindowのプロパティです。以前述べたようにwindowのプロパティはグローバル変数として利用可能

  • 外から与えるのは「指示」だけで、実際の動作は内部で行われるようなのがいいでしょう。 操作する側のページに長々とどう変更するかのコードを送らなくてよいので

  • window.postMessage()
  • 送ることができるメッセージは、プリミティブ(文字列とか数値とか真偽値とか)や、普通のオブジェクト、配列、Dateオブジェクトなどです。また、最近よく出てくるFile, Blob, FileList, ArrayBufferも送ることができます。

  • 第2引数は送る先のオリジンです。これは、意図しないサイトに向けて情報を漏らしてしまわないように、メッセージ送る先のオリジンを指定できる この第2引数は省略できません 現在と同じ"/" 何でもOK "*"

  • メッセージを送りつけるだけなら、同一オリジンポリシーに縛られずに送ることができる

  • window.addEventListener("message",function(e){ });

  • MessageEvent
  • e.data にメッセージの中身が入ってる
  • sourceプロパティがあり、これはメッセージの送信元のブラウジングコンテキストに対応するwindowオブジェクトが入っています これを使えばメッセージを送ってきたページに対してメッセージを送り返すことができます

2021/12/08 0:12 31m

十三章第四回 Web Messaging 2

https://uhyohyo.net/javascript/13_4.html

  • 2021/12/08 22:10 0m
  • window オブジェクトで他のタブとやりとりしてると、複数の通信先タブがあると混在すん問題ッ解決する
  • そこで、通信相手ごとに専用の回線を用意して、その中で通信することができます。これがチャンネルです MessageChannel

  • チャンネルメッセージングにおいては、windowオブジェクトではなくMessagePortにおいてmessageイベントが発生します。 あるMessagePortでpostMessageメソッドを利用すると、それで発せられたメッセージはもう1つのMessagePortに届き、messageイベントが発生します。

  • MessagePortは、startとcloseというメソッド(いずれも引数無し)を持ちます

  • 普通のpostMessageでMessagePortを送って、あとはそのMessagePortで通信してね ここで、window.postMessageの第3引数が登場します。これは当然ながら省略可能であり、指定する場合は配列を渡します。配列であるという点に注意しましょう。
  • この配列の中にMessagePortを入れてやれば、向こうに届きます。受け取る側では、これはメッセージではありませんからイベントオブジェクトのdataプロパティには入っていません。window.postMessageの第3引数に渡されたものは、イベントオブジェクトのportsプロパティとして配列のまま届きます。

  • portやり取り用引数
  • なぜMessagePortは第1引数で普通に受け渡せないかというと、第1引数のデータは全てクローン(コピー)して送られるのに対し、MessagePortではクローンではなく現物をそのまま送らなければならない、という理屈からだそうです。第3引数は、現物を送るための機能ということになっていますが、今はMessagePort専用です。第3引数に渡したオブジェクトは向こうに送られてしまったので、それ以降こちら側で使うことはできません。

  • 他のオリジンのページと通信したいときに役に立つかもしれません。

読み終 2021/12/08 22:21 10m  2700文字だった 確かに 300 chars / min

感想

  • XHR以外にも2種類の通信方式を学んだ
  • 1分間で300字読んでることがわかった

時間まとめ

  • 2021/12/6-8
  • 46 + 32 + 10 + 10(ブログ) = 98分
  • 累計: 1441分(24.0時間)

JavaScript中級者になろう 12章を読んだ (HTML5)

前: JavaScript中級者になろう 11章を読んだ (ES5) - t_hazawaの日記

経緯

  • JS力が必要
  • 楽しい

第十二章 HTML5+JavaScript

十二章第一回 classList

https://uhyohyo.net/javascript/12_1.html

  • html5の策定に伴ってhtml用のdomにも新しくて便利な仕様が加えられました。

  • ここに新しいクラスbbbを追加したいならば、 myDiv.className += " bbb"としてやることでclassNameは"aaa bbb"となります。
  • classListが無い時はclass削除は正規表現とかでclassNameをなんとかしていた
  • classListはいくつかのメソッドを持ち、それらによってclass属性をいじることができます

  • ちなみに、classListは仕様上はDOMTokenListというオブジェクトのインスタンス

  • 他の属性も同じものなので、同じメソッド使えるらしい
  • element.classList.contains("long")

  • element.classList.add("foo");

  • element.classList.remove("foo");

  • 確かにこれの前は jQuery でやってたね
  • toggle
  • item とか length もある
  • getElementsByClassName() も HTML5 から
    • ES5 じゃないんだな…?

十二章第二回 フォーム

https://uhyohyo.net/javascript/12_2.html (5000字...に対して↓の文章は 2400文字ある)

  • html5になって、フォームが大きく進化しました どのように進化したかについてはぜひ調べてみましょう。

  • html5のフォームには、妥当性(validity)という概念があります。各コントロール(inputなどの入力欄)にそれぞれ妥当性があります。 フォームは、その入力内容が全て正しいときのみ送信が可能になります。

  • 全然知らなかった
  • formNode.checkValidity() // true(妥当) / false
  • reportValidityの場合、妥当でない場合はユーザーにエラーが表示されます。

  • 実は、イベントハンドラの中ではthisはevent.currentTargetと同じもの、つまりそのイベントハンドラが登録されている要素を指すことになっています。

  • input要素をはじめとするフォームコントロールはformというプロパティを持っており、これはそのコントロールが属するform要素です(なければnull)

  • reportvalidityにより表示されるエラーは「送信」ボタンを押したときのエラーと同じはずです。 reportValidityはユーザーが慣れ親しんだui(ブラウザに備え付けのui)でエラーを表示することができるため、独自のエラー表示を作るよりも分かりやすいと考えられます。

  • reportValidity は、良い感じの見た目で 入力されてませんみたいに出る(特に文言を設定しなくても出る)
  • required="" で 必須要素にできるんだね というか required だけかけばいい
  • pattern="\d{7}" で、 input type="text" の適切な入力内容を指定できる
  • 知らないことだらけ
  • onChange はフォーカスはずれないと発動しない onInput は1も時ずつ
  • HTMLの属性(pattern)だと、CSSで色を変えたりもできるとのこと
  • title要素の内容はエラーメッセージとして表示されます。

  • 多分属性かな?
  • コントロールの妥当性に関してもっと詳細な情報を取得するために、input要素等のノードにはvalidityというプロパティがあります。 ValidityStateというオブジェクトのインスタンス

  • valueMissing とかいろんなプロパティがあるので、何が悪いのか分かる
  • typeMismatch type="email",type="url"の場合に、正しい書式でない場合にtrue。

  • すごそう
  • stepMismatch 数値入力コントロールで、strep属性で指定した単位とあわない場合true。

  • なんかすごそう
  • customError 独自エラー(後述)がある場合true。 i

  • つよそう
  • JavaScript側から「妥当である」とか「妥当でない」ということを決めてやることができる コントロールのノードが持つメソッドsetCustomValidity これは、引数を1つ持ち、それはエラーメッセージです。この関数を呼び出すとエラーメッセージが設定され、その要素は妥当ではなくなります。 "" で同じメソッドを呼ぶと、妥当になる

  • form に oninput をつけると、中のどこかがinputされたらイベント発生
  • 特に reportValidity を呼ばなくても、妥当でなかったら submit でいい感じにエラー文言が出るようだ
  • たとえばtype属性が"hidden"とか、あるいは"button"とかの場合はユーザーが入力するものではないですから、妥当であるとか妥当でないとかいう概念が無いのです。 (willValidate で false)

  • input type="range" というものがある
  • これは通常、 number 入力型のようなテキスト入力ボックスではなく、スライダーやダイアルコントロールを用いて表現されます。この種のウィジェットは厳密なものではないので、コントロールの正確な値が重要でない限り、通常は使用するべきではありません。

  • type="number" というものもある
  • 。。というinput要素では、値として0,10,20,30,40,…を入力できます。このようなinput要素に対してはstepUp及びstepDownというメソッドが使用できます。引数をnとすると、n段階だけ数値を上げ/下げるメソッドです。

  • 日付入力input 要素から11 valueAsDateは、日付をDateオブジェクトで取得できるプロパティです。Dateオブジェクトはこれまで紹介していませんでしたが、昔からある組み込みオブジェクトで、日付を表すものですす。 またvalueAsNumberは、日付を1970年1月1日の0時からのミリ秒数で取得できます。

十二章第三回 History API

https://uhyohyo.net/javascript/12_3.html

  • history.back(); とかは昔からあった
  • history.forward(); history.go(3);
  • HTML5での画期的な新機能は何かというと、履歴の追加です。勝手に自分で履歴を追加できるのです。

  • ブラクラに使えそう(20年前から来た人)
  • 今のURLも変えられる
  • history.pushState(null, 'テスト', '/javascript/testtest');

  • 第2引数は 履歴のタイトルだが、現状のブラウザは対応してない
  • 第一引数 state? でオブジェクトと履歴を結び付けられるらしい
  • history.replaceState() だと、追加ではなく上書き
  • 追加した履歴を消す方法はありません。

  • SPAでは、実際にはページ異動してないのでとても大事
  • 履歴移動の検知でページを書き換える
  • popstateというイベントを用いることで履歴移動を検知することができます

  • 別のページへ行ってしまう場合は発生しません。pushStateなどによって追加された履歴の間で(すなわち、同じページの中で)履歴を移動する場合に発生してくれるイベントです

  • window.addEventListener('popstate', function(ev){ }, false);

  • 移動後の履歴に関連付けられたstateオブジェクトがイベントオブジェクトのstateプロパティに入っています。つまり今回の場合はev.stateですね

  • WAI-ARIAというアクセサビリティを向上する属性がある
  • https://developer.mozilla.org/ja/docs/Learn/Accessibility/WAI-ARIA_basics
  • history.stateを紹介します。これは「現在の履歴」に関連付けられたstateが入っています。

  • ハッシュ以降も、locationで操作できる
  • locationには、urlの各部分をいじることができるプロパティがあります ハッシュの部分だけを変更するには、location.hashを使います。例えば先程の例だと、location.hashには"#abc"と入っています。

  • ハッシュを変更してもページは変わらないがURLは変わるので同じページのままURLを返るのに使えるね
  • ハッシュを変更すると新しい履歴が追加されます 「戻る」ボタンが押されると同じページの中でハッシュだけが違うurlに移動することになります。同じページ内での履歴移動ということはpopstateイベントも発生します。

  • popstateと似たイベントとして、履歴移動のうちハッシュだけが変わった場合に発生するhashchangeイベントがあります

  • hashchangeイベントのイベントオブジェクトにはoldURLとnewURLという2つのプロパティがあり

  • hashchange イベントを使うと、openTab() みたいなのを呼ぶ箇所を減らせるとのこと
  • ハッシュを用いて履歴を管理することには、場合によってはもうひとつ大きな利点があります。それは、ページの状態とurlが対応するという点です urlからページの状態を復元可能

  • location.assign URL要素を一個ずついれられる
  • location.replace という上書き版もあるらしい
  • location.reload 更新

十二章第四回 dataset

https://uhyohyo.net/javascript/12_4.html

  • みんなだいすき data-honyarara
  • element.dataset.foo で読み書きできるよ
  • なお、属性名にハイフンが含まれていた場合キャメルケースに変換されます。つまり、例えばdata-foo-barという属性はdataset.fooBarというプロパティに対応します。

十二章第五回 File API

https://uhyohyo.net/javascript/12_5.html (10000字。↓は3500字)

  • 自由にファイルを見られてはセキュリティも何もあったものではないので、ユーザーが認めたファイルのみ見ることができるという安全仕様です。 具体的には、javascriptでどのファイルを読み込めるのかをユーザーに選択してもらう必要があります。

  • input type="file" で選択されたファイルはJSから読める
  • input要素から選択済みファイルを取得するには、このinput要素のfilesプロパティを調べます。このfilesプロパティに入っているのが、FileListオブジェクトです もしかしたら複数ファイルが選択されている可能性がある

  • length と item でいい感じに取得できる
  • filelist[0] でも取れる
  • この中に入ってるのが Fileオブジェクト
  • FileオブジェクトというのはBlobオブジェクトの一種で(つまり、FileはBlobを継承しています) Blobとは何かというとバイナリデータを表すオブジェクト、要するにファイルの中身そのものを表すオブジェクト

  • FileReaderオブジェクトで中身を取れる
  • これの特徴は非同期読み込みであるということです。JavaScriptで非同期といった場合、意味するところはコールバックで結果を得るということです。

  • async/await も今の所マだ謎の要素
  • fileReader.readAsText()
  • 同期だと プログラム側は関数の処理が終わるまで待つ このようにプログラムが待たされることをブロックするといいます

  • 今回の場合、readAsTextを「終わったら呼んでね!」と言って呼び出し

  • コールバックにイベントはニている イベントハンドラが呼ばれる
  • コールバックはだいたい1会呼び出し、 イベントは複数回ありうる
  • 1回だけ発生するイベントがコールバックであるという見方もできます。

  • var reader=new FileReader();

  • var reader=new FileReader();
  • reader.onload = function(e){
  • console.log("読み込みが終わりました");
  • };
  • reader.readAsText(file);
  • プロパティにコールバック関数を入れると、終わったときとかに読んでくれる
  • readAsTextは、第一引数にBlob(今回はFileなのでさっき読み込んだFile)を渡します。

  • 人によっては、「readAsTextが一瞬で読み込み終わったらonloadプロパティを設定する前に呼ばれてしまうかもしれない」と思うかもしれませんが、その心配をする必要はありません。詳しくは解説しませんが、これは非同期的にコールバックが呼び出される場合、必ず今まさに実行中の一連のプログラムが最後まで実行されてから呼びだされるからです。

  • 今回のプロパティonloadですが、これはどう見てもイベントloadのイベントハンドラに見えます。上で「コールバックは1回だけ呼ばれるイベントである」というようなことを述べましたが、今回はまさにそうなっています

  • イベントハンドラっぽい名前になりがちなコールバック関数設定用プロパティ
  • 実は、おなじみのaddEventListenerメソッドを使ってイベントを登録する方法もあります。

  • コールバック関数の第1引数eはイベントオブジェクト

  • コールバック関数にもイベントオブジェクトが引数で渡ってくる
  • この場合のe.targetはFileReaderオブジェクト(上の例だとreader)が入っています。

  • イベントオブジェクトe にはよく e.target がある
  • 読み込みが終わった時点で、読み込み結果はどこに入っているのかというと、FileReaderオブジェクトのresultプロパティに入っています もちろん、e.target.resultでも同じです

  • 起こることが順番に書かれないのでわかりにくいコールバック 読み終わったら起こること→読ませる の順
  • そのファイルをどんな文字コードで読み込むかは第2引数で文字列で指定します。第2引数がない場合はUTF-8になります。他に"UTF-16"とか、"Shift_JIS"などなどが使えます。

  • FileReader.readAsArrayBuffer();
  • ArrayBufferとは
  • ArrayBufferの特徴は、実際にメモリ上に連続する領域が確保されているということです。ファイルをBlobとして得られた段階では実はBlobオブジェクトが作られただけで、まだそのファイルをメモリ上に読み込んでいないかもしれません。それを実際にメモリ上に(文字列やArrayBufferの形で)読み込むのがFileReaderなのだということですね。

  • このArrayBufferというのは先々また出てくるわりと汎用的なオブジェクトなのでここで慣れ親しんでおきましょう

  • ArrayBufferはバイナリデータなのですが、実はその中身を読むにはさらに別のオブジェクトが必要なのです。面倒ですね。

  • すごくめんどくさそうな話になってきた
  • それが型つき配列(TypedArray)であり、このオブジェクトによってArrayBufferの中身をどのように(1バイトずつとか、4バイトずつとか)読むかが定まります。

  • よく使いそうなUint8Arrayから紹介しましょう。Uint8とは、「8ビットで符号なし整数」 1バイトずつ読める(8ビット=1バイトなので)

  • バイナリデータはバイト単位で区切って表示されることが多いように思いますから、これが最も自然なのではないでしょうか

  • UInt32Array (4バイト)とかある Float32Array とか TypedArray
  • var arr=new Uint8Array(buffer);

  • newで作ろう TypedArray
  • TypedArray でいじると、もとの ArrayBuffer にも反映されるよ まさにビューワー
  • ArrayBufferがメモリに確保して、そのメモリのデータをTypedArrayで操作する
  • TypedArray.length 長さ
  • ArrayBuffer.byteLength
  • arr[0]で読み書きもできるぞ
  • readAsDataURLの前まで 2021/12/01 21:10 44m
  • data: から始まるURLを読める readAsDataURL
  • DataURLというのは、データがURL内に全部書いてあり、インターネットアクセスをする代わりにURL内のデータを読むことで結果を得られるものです。

  • data:text/html,%3c%21doctype%20html%3e%3chtml%3e%3cbody%3e%3ch1%3etest%3c/h1%3e%3c/body%3e%3c/html%3e

  • ブラウザに入れると htmlとしてレンダリングされる
  • このように、ブラウザが読み込んだとき、あたかもどこかからその内容を取ってきたかのように振る舞うのがdataurlです。

  • readAsDataURL だと劇ながになることあるので URL.createObjectURL が便利
  • このメソッドにblobを引数として渡すと、オブジェクトurlと言われる特殊なurlが生成されます このurlはブラウザが発行したurlであり、そのページが閉じられるまで有効です。

  • このurlは、その内容(blob)をブラウザが覚えておき、それを指し示すものです。 データの本体はurlに書いてあるわけではなくブラウザの内部に保管されています。

  • Object URL 知らなかったなあ
  • var objurl = URL.createObjectURL(file); でつくれる

  • URL.revokeObjectURLメソッドを呼び出して(第1引数にオブジェクトURL) すると親切
  • なんかTypedArray に自分で色々データを入れてつかうことがあるらしい
  • エンディアン バイトを並べる順序のこと このせいで 2バイト以上の TypedArray は使い所が限定されるとのこと

十二章第六回 Drag and Drop API

https://uhyohyo.net/javascript/12_6.html

  • こっちも7200文字ある
  • ドラッグできる要素を作る

  • ファイルを投げ込む話しじゃなかった
  • html5のdraggable属性
  • draggable="true"
  • 単にその編の要素にかかけてもドラッグできない
  • a要素やimg要素はもともとドラッグできる

  • なるほど、あの挙動がドラッグできるということか
  • dragenterイベント
  • これは、ドラッグしながら他の要素の上にさしかかったときに発生するイベントです。

  • dragenterイベントのデフォルトアクションは「ドロップ先をbody要素に変更する」 すなわち、dragenterイベントが発生すると、どこにマウスを持って行っても全部body要素にドロップした扱いになってしまいます。

  • ですから、どこに置いてもbody要素にドロップした扱いになるのはちょっと困ります。そこで、dragenterイベントのデフォルトアクションを無効にする必要があります(これを、イベントをキャンセルするといいます) - - preventDefault - どこでpreventDefault しないといけないか知識も、JavaScript 難しさ (全部につけられれば楽そう)

  • さらに面倒なことに、実はもうひとつキャンセルすべきイベントがあります。それはdragoverイベントです

  • 驚きのめんどくささ
  • ドラッグオペレーション四種類 copy link move none
  • 実際にドロップしたときの動作はやはりJavaScriptで記述するので、ドラッグオペレーションには表示以上の意味はそんなにありません。しかし、値が"none"になっている場合はドラッグ&ドロップ自体が無効になってしまうので、何か他の値にセットする必要があります。

  • その方法ですが、dragenter,dragoverなどのDnD APIに関係するイベントでは、そのイベントオブジェクトはDragEventといい、dataTransferプロパティを持ちます。これをDataTransferオブジェクトといい、ドラッグ&ドロップに関するさまざまな情報を管理します。 - ???

  • 仕組みとしては、dragenter、dragoverなどのDnD APIに関連するイベントの場合、イベントオブジェクトはDragEventと呼ばれ、dataTransferプロパティを持っています。これはDataTransferオブジェクトと呼ばれ、ドラッグ&ドロップに関する様々な情報を管理しています。

  • //elmは適当なHTMLElementとする

  • elm.addEventListener("dragover",function(e){ e.dataTransfer.dropEffect = "copy"; e.preventDefault(); });
  • というようにすればいいらしい
  • dragoverのデフォルトアクションは「ドラッグオペレーションを"none"にする」ということなのです。

  • 確かにポインタが変わってる
  • dropイベント
  • イベントオブジェクトのtargetプロパティはドラッグ先の要素です

  • event.target は常連
  • dataTransfer には ドラッグされたもののデータを格納しておけるとのこと
  • ドラッグ&ドロップにおけるデータの流れは、「ドラッグされる側がdataTransferにデータを格納する」→「ドロップされたとき(dropイベント)にdataTransferからデータを取り出す」ということになります。

  • dragstart イベントでデータを dataTransfer オブジェクトに格納する
  • dataTransfer.setData()
  • 第一引数がフォーマットの文字列、第二引数がデータの文字列です。

  • mimeの後ろの方は x- から始まる自由文字列使える
  • この部分には"x-"から始まる自由な文字列を設定できるので、例えば"text/x-mydata"とかです。

  • dataTransferには複数のデータ から
  • 2021/12/04 23:11
  • dataTransferには複数のデータを格納することができますが、同じフォーマットのものは複数格納できません。

  • document.addEventListener("dragstart",function(ev){ ev.dataTransfer.setData("text/plain",ev.target.textContent); });

  • 同じようにaddEventListenerでイベントを付加してもいいのですが、面倒なのでondrop="drop(event)"のようにしてdropという関数を作ってそれに渡すことにしましょう。

  • イベント属性では勝手に event という引数をつけてくれるっぽい
  • function drop(ev){ var data = ev.dataTransfer.getData("text/plain"); }

  • dropイベントでも最後にpreventdefaultしているのが分かると思います。これは、(2014年7月現在)firefoxがドロップ後にページ遷移してしまうので、それを防ぐ目的があります。

  • 実は、img要素がドラッグされる場合自動的にdatatransferに画像のurl(具体的にはsrc属性の内容)が格納されます。その際のフォーマットは"text/uri-list" 複数のimg要素が同時にドラッグされている場合もあります。そのようなときは、全てのurlが改行で区切られた文字列が入っています

  • 実はa要素の場合も、そのリンク先のurl(href属性)が"text/uri-list"で入っています。

  • 実は、デフォルトでドロップ可能な要素も存在します。それはtextarea要素およびinput要素(type="text"の場合)です 実は、"text/plain"のデータがdatatransferに入った状態でこれらの要素にドロップされると、その内容が入力されます。

  • 。dragstartをキャンセルした(preventDefaultでデフォルトアプションを無効化)した場合はその要素はドラッグできません。

  • dragleaveイベント 実は、dragleaveイベントのイベントオブジェクトのrelatedTargetプロパティは移動先の要素を示しています。

  • ドラッグを続けている間、ドラッグされている要素ではdragイベントが発生し、ドラッグ先の要素ではdragoverイベントが発生します。 ブラウザにもよりますが、1秒に数回程度のペースで発生します。先に述べたようにdragoverはキャンセルしなければドロップを受け入れられません。

  • dragイベントをキャンセルした場合はドラッグが中断されます。ドラッグを強制的に止めたい場合はdragイベントをキャンセルしましょう。

  • dropeffectが"none"の場合など、ドロップが受け入れられない状況でドラッグが終了した場合はドロップ扱いにならず、dropイベントは発生しません。

  • dragendイベントがドラッグされている要素で発生します dragstart→drag→drag→……→drag→dragend dragenter→dragover→dragover→……→dragover→dragleave 最終的に要素が話された地点ではドロップ先の要素でdropイベントが発生

  • dataTransfer内のデータにアクセスできるのはdragstartイベントとdropイベント

十二章第七回 Drag and Drop API 2

https://uhyohyo.net/javascript/12_7.html

  • 4900文字
  • 実はページの外から何かがドラッグされてくるという場合もあります

  • 僕が最初考えてたDnD
  • 実は、ファイルをjavascriptから読み込む方法はもう1つあります。それが、ブラウザ内へファイルをドラッグ&ドロップしてもらうことです。

  • 言われてみればこの二種類しかないね
  • 実は、ページの外からファイルがドラッグ&ドロップされてきた場合も、ドロップ先の要素ではdragenter、dragoverその他のイベントが発生します。 実は、dataTransferはfilesというプロパティを持っており、これはFileListオブジェクトです

  • p.textContent= file.name;
    

    ev.target.appendChild(p);

  • ちなみに、紹介しそびれたdataTransferのメソッドで、clearDataというものがあります。これはフォーマット文字列を引数にとって呼び出すことで、そのフォーマットのデータをdataTransferから削除できます。

  • dataTransferを扱うメソッド(setData, getData, clearData)は実はちょっと古い方法で、最新の仕様では新しい方法が用意されています

  • なんか先に廃止サれそう
  • というか、現在(2019年7月)でもSafariというブラウザが未だに未対応となっています。そのため、以下の内容は今すぐ実用できないかもしれません。

  • 新しい方法では、DataTransfer内のデータはdataTransferが持つitemsプロパティに集約されます DataTransferItemListオブジェクト

  • この新しい方法の特徴は、addメソッドの第1引数に別の方法で生成したFileオブジェクトを渡すことでdataTransferにファイルを追加することができる

  • 古い方法では、ブラウザウィンドウの外からファイルをドラッグしてきた場合しかDnD APIでファイルを扱う機会はありませんでしたが、新しい方法ではこのようなパターンもあるのです

  • しかも、dataTransfer.items[0]のように取得したデータは生のデータではありません。ここで得られるのはDataTransferItemオブジェクトというもので、このオブジェクトからさらにデータを引き出すのが少し面倒 文字列の場合はgetAsStringメソッドで、ファイルの場合はgetAsFileで生のデータを取得します

  • 面倒そう
  • getAsStringメソッドの場合はさらに面倒です。このメソッドには引数でコールバック関数を渡す必要があり、その関数にデータが渡されます。

  • 普及しなさそう
  • 特に、この方法によって中にどのようなデータ(データのフォーマットや種類)が入っているかを知ることができます。前回dragstartイベントとdropイベント以外ではdataTransfer内のデータを見ることができないと解説しましたが、実は実際のデータを見ることはできないもののデータの種類などの情報は見ることができます。これにより、例えばdragenterイベントで、データの種類によって受け入れるかどうかを決めるというような挙動が可能になります。

  • dataTransfer.items.addとdataTransfer.setDataにはひとつ違いがあります。既に存在するタイプのデータを追加しようとしたとき、前者はエラーとなるのに対し後者は上書きします。

  • ちょっとふみそう
  • 実は、DataTransferには、setDragImageというメソッドがあり、ドラッグ中に表示する画像を設定できます。例えばdragstartでこれを呼び出すと、ドラッグ中のマウス等の画像表示を変更できる dataTransfer.setDragImage( element, x,y); elementというのは、画像として使用する要素です。一般的にはimg要素ですが、他にも任意の要素を指定可能です。x,yは数値で指定します。これは画像のつかむ場所を示す座標です。

  • ドラッグオペレーション(copy・link・move)

  • moveしかしらないような…
    • ググッテュ情報でてこなかった
  • 例えばwindowsでは、普通にドラッグすると移動(move)だけどctrlキーを押しながら移動するとコピー(copy)になります。気が利くブラウザならばそういった情報を与えてくれるでしょう。しかし、あまり期待するべきではありません。 uninitializedの場合は何をドラッグしているかによってさらに気を利かせてくれます

  • ドラッグに種類があるのね

感想

  • Form の 妥当性は全然知らなかった

時間まとめ

  • 2021/11/29 - 2021/12/5
  • 38 + 48 + 45 + 39 + 34 = 204分
  • ブログ 25分(入力システム不具合で6分つまった) 合計 229 分
  • 累計1343分 (22.4時間)

JavaScript中級者になろう 11章を読んだ (ES5)

経緯

  • 業務プロダクトをTSにする前に、JS力を高めようとなったので続き

感想

  • JSはES5 だけでなく、ES2015-2017 で段階的に強化されたのだなあ (classはES5ではなかった)

構成

11章 ES5

十一章第一回 配列 (かなりnagai、31分)

  • https://uhyohyo.net/javascript/11_1.html

  • array.lengthはarray["length"]としても参照可能 プロパティはこのような形でも三章可能 - 前にも説明あったと思う

  • プロパティ名に文字列以外が渡された場合は文字列に変換されます 数字から始まるプロパティ名の場合はarray.0のようにドットを使って参照することはできません

  • push & pop
  • pushは、配列の最後に要素を追加 popは引数がなく、最後の要素を取り除きます。取り除いた要素は戻り値となります。

  • 逆に、最初に要素を追加するメソッドもあります。それがunshiftです。一方、最初の要素を取り出すのがshiftです。

  • hairetsu.splice(1,2) 2※から2つぬき出す
  • array.splice(1,1,"小沢一郎");

  • 鳩山由紀夫小沢一郎になる
  • 4つ、5つとさらに入れるものをふやせる
  • array.reverse();
  • array.sort();
  • 引数なしなら辞書順 (コードポイント順)
    • 数値大照準ではない
  • 0未満ならaのほうがbより小さい(aのほうがbより前)、0より大きいならaのほうがbより大きい(aのほうがbより後)、0なら同じ

  • return a-b; が簡単

  • array.sort(function(a,b){return a-b});

  • 無名関数版
  • .sort() も破壊的メソっょ
  • var newarray = array1.concat(array2);

  • var newarray = array1.concat('鳩山由紀夫','菅直人');

  • 配列を文字列にする .join()
  • console.log(array.join("→")); // "麻生太郎鳩山由紀夫菅直人"

  • .slice() も非破壊的
  • 引数はspliceと違って、 slice(開始位置, 終了位置)
  • 終了位置の一つ前まで返す
  • indexOf、ないときは-1
  • 第2引数に探し始めるところがある (つかわなさそう)
  • 後ろから探す lastIndexOf()
  • ES5で登場した foreach
  • array.forEach(function(x){ var li=document.createElement("li"); li.textContent=x; ul.appendChild(li); });

  • まぁ for とあまりかわらないかな?
  • 主な利点は、カウンタ変数(for文を使ったさっきのサンプルの場合、変数i)がいらない

  • 第2引数は現在の添字、第3引数は現在処理している配列そのもの
  • mapは同じ引数が関数にくる。return すると、return した結果からなる配列を map が返す
  • JSにはメソッドチェーンがあるよ 2021/11/23 21:05 25m
  • .filter(function(){}) は、 funcが true (になるものを)返したものだけの配列を返すよ
  • every,some:配列の各要素に対する条件判定。。配列があって、「その中のどれか1つでも条件を満たせばok」とか「全て条件を満たせばok」という状況があります

  • someは、配列の要素の中でコールバック関数がtrueを返すものが1つでもあればtrueを返し、1つもなければfalseを返します

  • array.some(function(x){return x<=5;})

  • reduceです。これは関数型プログラミング言語の界隈ではfold(あるいはfold_left)と呼ばれています。

  • var sum=array.reduce(function(s,val){ return s+val; }, 0);

  • 第1引数がそれまでの計算結果、第2引数が配列の要素
  • 返り値はこの要素も含めた計算結果
  • 逆からやる reduceRightもあります。

2021/11/23 21:11 読み終 31m

十一章第二回 bind

https://uhyohyo.net/javascript/11_2.html

  • bindは九章第五回でちらっと出てきたもので、ある関数が呼ばれたときのthisの値を固定するためのメソッドです。

  • var foo = showThis.bind("菅直人");
  • function showThis で this を固定した関数を作る
  • コールバック関数の中でも外側のthisの値を使いたい場合など、thisの値を保存したい場合には役に立ちます

  • bindはthisだけでなく引数も固定できます

  • var foo = sum.bind(null,10);

  • this を null にして固定せず、最初の引数を固定してる

十一章第三回 console

https://uhyohyo.net/javascript/11_3.html

  • console.logの仲間
  • consoleという変数に入ったオブジェクトが持つlogというメソッド

  • console.debug,console.info,console.warn,console.error

  • これらは、 console.log の重要度が違う版、アイコンがかわったりする
  • 大量にログ出すときは便利かもね
  • console.dirは、「オブジェクトの場合はそのプロパティ一覧を表示する」というはとになってる
  • conosle.log の強い版 プロパティ一覧が見やすいらしい
  • console.assert 第一引数に条件、第二引数以降が今まで同様に表示するもの
  • 条件true で何もコンソールにださない
  • falseなら、第二引数以降の内容を表示しつつエラーを発生させて停止します(九章第八回で紹介したthrowと同じ感じです)

  • console.trace。。これは引数なしで、コンソールに現時点でのコールスタックを表示します

  • console.groupは、コンソールに表示されるログをグループ化します

  • console.group自体にも引数を指定することで、通常どおりログに表示させることができます。。。console.groupが呼び出された後に続くログは、そのconsole.groupのログを親としてまとめられ(グループ化)、まとめて折りたたんだりできるようになります。このグループ化は、console.groupend(引数なし)が呼び出されるまで続きます。 ちなみに、groupCollapsedというのはgroupと同じですが、最初からそのグループが閉じてまとまった状態で表示されます。

  • profileが呼ばれてからprofileEndが呼ばれるまでの、実行時間などのデータを取得できます。ちなみにprofileには引数を指定することができ、あとで結果を表示するときにそのタイトルとなります - ◎便利そう console.profile

  • console.time?console.timeEndです。これは要するにタイマーで、timeが呼ばれてからtimeEndが呼ばれるまでの時間を測定します。測定結果は、timeendのときにコンソールに出力されます

  • console.countが呼ばれるたびに数字を1増やして出力します

2021/11/25 1:14 11-3 おわり 2021/11/25 1:14 17m

十一章第四回 Objectとプロパティ

https://uhyohyo.net/javascript/11_4.html

  • ES5の特徴は、オブジェクト、特にプロパティに対する操作が強化されたことです。

  • オブジェクトリテラル
  • var obj={ foo:"bar", baz:3, };
  • 古典的な方法としてはfor-in文があります。これは以下のような形の文です。 for(var 変数名 in オブジェクト){} for(var key in obj){ console.log(key);} 左の変数に、右のオブジェクトが持っているプロパティの名前が入り、全てのプロパティについてループします console.log(obj[key]); 中身

  • 従来(ES5以前)はプロパティの一覧にアクセスする方法はこれだけでしたが、ES5においては新しい方法が用意されました。 それはObject.keysメソッドです names.forEach(function(name){ console.log(obj[name]);});

  • prototype のメソッドかどうかは ES5になってから気にすることが多くなったとのこと
  • for-in文はそのオブジェクト自身がもつプロパティだけでなくprototypeを介して参照するプロパティも列挙する

  • enumerable属性です。日本語にすると「列挙可能性」 enumerableがfalseの属性はfor-in文やObject.keysで列挙されない 属性は全部で3つあります。writable,enumerable,configurableで、いずれもtrueかfalseかです。 es5より前のjavascriptにおいてはこれらの属性は完全に内部的なもので、スクリプト側からどうこうすることはできませんでした。

  • 属性(など)をいじるには、プロパティデスクリプタを使います。これはプロパティの属性を含む諸々の情報を表すオブジェクトです。Object.getOwnPropertyDescriptor var desc = Object.getOwnPropertyDescriptor(obj, "foo"); obj["foo"] についての情報を要求 { writable: true, enumerable: true, configurable: true, value: "bar" }

  • console.log(Object.getOwnPropertyDescriptor(Object.prototype,"toString"));

  • { writable: true, enumerable: false, configurable: true, value: function toString() { [native code] } }

  • 中身はブラウザの内部処理なのでjavascriptでは表現できないといういみ

  • Object.defineProperty

  • Object.defineProperty(obj,"hoge",{ writable:false, enumerable:true, configurable:true, value:"hogehoge" });

  • configurableがfalseであるプロパティの属性はいじれません。すなわち、definePropertyしようとするとエラーになります。 writableもfalseにしておけば、もはやそのプロパティの内容は絶対に不変であることが保証されたようなもの

  • Object.prototypeのようにいじられたら大惨事になるプロパティは、いじれないようにwritableとconfigurableがfalseになっています

  • 実は、ゲッタとセッタについてもdefinePropertyを用いて設定できます

  • defineProperty で get: とか set: に関数を磯ル (正式なやり方)
  • getとsetがある場合writable属性は無視されます valueもいりません

  • 既存のプロパティに対してobject.definePropertyを使うこともできます 第三引数のオブジェクトで変えたいところだけを指定できる

  • 作成時省略された属性はfalse

  • object.defineProperties 複数プロパティを一度に作ったり変えたりする
  • Object.defineProperties(obj,{ foo:{ value: "bar", configurable:true }, bar:{ value:3, enumerable:true } });
  • 第二引数はオブジェクトで、設定したいプロパティ名をキーにしてプロパティデスクリプタを値としてもつ辞書オブジェクト

  • Object.getOwnPropertyNamesを紹介します。これは、基本はObject.keysと同じですが、enumerableがfalseのプロパティも列挙する

  • Object.hasOwnProperty() 渡した名前のプロパティが自分自身にアるか Own なので、prototypeチェーン遡らない 
  • enumerableがfalseなプロパティであっても正しく判定してくれます

  • in演算子というのがあります。これも同じようにプロパティが存在するかどうかを確かめる動作をしますが、prototypeチェーンまでさかのぼって探す console.log("attack" in zako); //true

  • このin演算子はfor-in文のinとはあまり関係ないので注意しましょう。

  • Object.propertyIsEnumerable("propertyName") // true/false
  • そもそもなかったら false

11-4 プロパティ話おわり (つづく) 2021/11/25 1:46 39m (いうほど、続く回での話は近い話ではなかった)

十一章第五回 プリミティブについて

https://uhyohyo.net/javascript/11_5.html

  • プリミティブはオブジェクト以外のもの

  • JSの世界には 数値、文字列、真偽値、undefined,null, オブジェクトの六種類のものしかない
  • hoge = "mojiretsu";
  • typeof hoge; // "string"
  • typeof では オブジェクトは "object" か "function" になる
  • typeof では null は "object" になってしまう (歴史的経緯)
  • if(typeof a=="object"&&a!=null){。} とかかく

  • プリミティブにプロパティはないが、. をつけるとString みたいなオブジェクトになる
  • プリミティブに対応したオブジェクトのインスタンスが一時的に作られる

  • nullとundefinedには対応するオブジェクトがないので変換できず、nullやundefinedのプロパティを参照しようとするとエラーになります。

  • "abc".charCodeAt(0)は97 a が 97 だから

  • "aaa".concat("bbb","ccc","ddd") // "aaabbbcccddd"

  • 配列とは異なり文字列は+で繋げられるので使う機会はやや少ないかもしれません。

  • 配列は + で繋げられないのかあ
  • "01234567890123456789".lastIndexOf("123") // 11

  • "012340123401234".indexOf("abc",2) // 6

  • 検索開始位置指定できる これも0はじまり
  • lastIndexOfの場合、前から数えた位置を渡してあげるとその位置より後ろは無視されます。

  • a.localeCompare(b)

  • aのほうがbより先なら負の値、aとbが同じなら0、aのほうがbより後なら正の値

  • 辞書順は必ずしもコードポイント順ではない
  • “n”(なんか上についてるやつ)は、コードポイントU+00F1を持ち、普通のaからzのアルファベット(U+0061?U+007A)よりずっと後ろにあります。ところが、localeCompareで比べると多くのブラウザではnはnとoの間にあるのではないかと思います。

  • localeCompareの第2引数に言語を指定することができます。言語は文字列で指定します。例えば日本語は"jp"で、英語は"en" IETF言語タグ

  • matchの場合はマッチに関する情報を配列で返して、replaceの場合は置き換え後の文字列 searchは位置番号

  • "abc123def".search(/\d/) // 3

  • "aaa,bb,c,dddd,ee".split(",") // ["aaa","bb","c","dddd","ee"]

  • "fff1ghi2jjjkkk0lmn".split(/\d/) // ["fff","ghi","jjjkkk","lmn"] - ☆なんと String.split() は正規表現もtukaeる

  • "fff1ghi2jjjkkk0lmn".split(/(\d)/) // ["fff","1","ghi","2","jjjkkk","0","lmn"] - ◎ ()でくくると、区切り文字が配列に入る

  • splitには第2引数があり、これがある場合配列の要素数の上限

  • toLowerCase, toUpperCase - 結構使うイメージ

  • "Ω".toLowerCase() // "ω"
  • "φ".toUpperCase() // "Φ"
  • "a".toUpperCase() // "A"
  • toLocaleLowerCase, toLocaleUpperCase

  • 言語に合わせて LowerとかUpperにする
  • 言語設定がトルコ語の場合のみ"I".toLocaleLowerCase()が"?"などとなります

  • ブラウザに言語設定があるので、引数でlocaleを指定しなくてもいい感じになるっぽい
  • String.trim() も便利

読み終わり 2021/11/25 19:45 33m

十一章第六回 プリミティブについて2

https://uhyohyo.net/javascript/11_6.html

  • 半壊は数値とか
  • JSはぜんぶ Number
  • Infinity NaN
  • Infinity も number
  • Number.POSITIVE_INFINITY
  • 数学的に結果が決まらないときが NaN これも number
  • console.log(typeof Number.NaN); // "number"
  • NaNを含む計算の結果が全てNaNとなる
  • 文字列から数値への変換時に、変換できない文字列はNaNになります

  • parseInt("123px") // 123

  • Number("123px") // NaN

  • parseInt("10000", 2) // 32 基数は、2から36まで可能

  • parseInt("z",36) // 35

  • zまでしか文字がないから 36進数まで
  • NaNが入ると比較は全てfalse
  • isFinite (有限か)
    • infinity や Nanでなければ true
  • nullもリテラルです。一方、実はundefinedはリテラルではなく変数ということになっています。スクリプト上にundefinedと書いた時はそれはundefinedのリテラルではなく、undefinedという値が入った変数が予め用意されているだけなのです。しかし、writable属性(十一章第四回参照)がfalseになっているので書き換えられません。

  • 正規表現リテラルもあるぞ
  • /ab+c/
  • マイナスがついたのはひとまとまりの数値リテラルではなく、単項演算子の-(マイナス)の後に数値リテラルがくっついた値であるということです。その証拠に、

  • console.log(- 100);
  • のようにマイナスを離しても動作します。
  • 単項演算子-は、簡単にいうと数値の符号を逆にして返す演算子

  • console.log(-num); // -10

    1. は 3.0 になる
  • 1e4 // 10000
  • 5.E2 // 500
  • あとは16進数
  • 0xff // 255
  • 0xDEADBEEF // 3735928559
  • console.log(num.toString(2)); // "1010"(2進法で10)
  • 基数がある Number.toString()
  • console.log(a.toLocaleString()); // "30,000"

  • 5.1.toFixed(5)//5.10000

  • 123456.789.tofixed(2)//123456.79 四捨五入

  • toExponential(小数点以下の桁数)
  • toPrecision 有効数字
  • NumberのメソッドはStringにするものばかり
  • 3.toExponential(2) は 3.0toExponential(2) になるからエラーになる
  • () とか .. にする
  • Number.MAX_VALUE 扱える数値の範囲を出してくれる MIN_VALUE
  • Boolean.prototypeには特にメソッドはありません。

2021/11/26 23:19 40m

十一章第七回 継承2

https://uhyohyo.net/javascript/11_7.html

  • 難しそう
  • ES5で可能になったよりよい継承の方法

  • ソウソウョES3では なんか複雑な prototype といろいろを書かないと行けなかった
  • console.log(Object.getPrototypeOf(zako1) === Teki.prototype); // true

  • インスタンスの側からprototypeを取得できるのは、今までに無かったES5の新しい機能です(ただし、非標準のprotoというやつはありました)。

  • インスタンスの方からprototype を取れるらしい
  • console.log(Teki.prototype.isPrototypeOf(zako1)); // true

  • instanceofとの違いは、コンストラクタに対して使うかprototypeオブジェクトに対して使うか

  • isPrototypeOf は .prototype のメソッド
  • console.log(boss instanceof Teki); // true

  • オブジェクトにつかえる instanceof
    • 全部小文字なのか…
  • 継承にかかわるのはDragonコンストラクタ内の Teki.apply(this,arguments); と、プロトタイプの Dragon.prototype = new Teki; のところでしたね。

  • あまりに直感的でないES3のけいしうょ
  • 継承したときに コンストラクタの処理がされるのが大問題
  • そこで、ES5ではこの問題を解決する方法があります。それがObject.createです

  • うーん、 classはいつできたんだっけ
  • これは第一引数にプロトタイプオブジェクトを指定すると、それをプロトタイプに持つオブジェクトを作成します。つまりこんな具合です。

  • var zako2=Object.create(Teki.prototype);
  • オブジェクトが他のコンストラクタのインスタンスであるかどうかは、オブジェクトと関連付けられたprototypeオブジェクトのみによって特徴付けられます (コンストラクタは呼ばれなくてもいいよ)

  • var zako2=Object.create(Teki.prototype);

  • Teki.call(zako2);
  • 2行目のcallは、Teki関数を、zako2をthisとして引数なしで呼べという意味ですね。コンストラクタはnewで呼ばれるときはthisの値が特別になっていたので、call(またはapply)を使ってそれを再現すればできます。

  • コンストラクタも関数なのだった
  • Dragon.prototype = Object.create(Teki.prototype);

  • のようにシンプルに継承できるらしい classがほしいね
  • Object.createに第2引数が渡された場合、インスタンスを作った後に第二引数で指定されたようにプロパティをセットして返してくれる

  • function Dragon(){ Teki.apply(this,arguments); } Dragon.prototype=Object.create(Teki.prototype,{ attack:{ configurable:true, value:function(){ console.log("ドラゴンのこうげき!!"); }, }, });

  • うーんなるほどね (classしか使わなさそうな気がしている)
  • console.log(zako.constructor === Teki); // true

  • コンストラクタを調べられる
  • 実は、関数が作られた時点で、その関数のprototype.constructorにはその関数自身が自動的に入っている状態になります。

  • なんとめんどくさいことに、 Dragon.prototype.constructor に Dragon を入れないといけない

おわり 2021/11/28 0:07 14m

十一章第八回 凍結と封印

https://uhyohyo.net/javascript/11_8.html

  • かっこいい 2021/11/28 0:22 0m
  • オブジェクトに関するいくつかのメソッド オブジェクトに対する変更を制限

  • writable属性をfalseにすれば、個々のプロパティについては書き換え不能にすることができます。しかし、新しいプロパティを追加されるような事態に対しては対応不可能

  • Object.preventExtensions(obj);

  • delete演算子によりプロパティを削除することはできます 既存のプロパティに対する操作は自由にできます

  • ◎ delete 演算子便利そう
  • Object.isExtensible() で調べられる 一度拡張不可能にされたオブジェクトは拡張可能に戻すことはできません。

  • 多分 ↑が 凍結?ちがうか 拡張不可能カ
  • Object.sealです。順番が前後しますが、これが封印ですね。このメソッドは、オブジェクトを拡張不可能にするのに加えて全てのプロパティのconfigurable属性をfalseに設定します。 writable属性は変更されません。ということは、既存のプロパティは依然として変更可能

  • なんか、実用では使わない気がしている…??
  • Object.isSealed

  • Object.freezeです。これが凍結 オブジェクトを拡張不可能にします。さらに、既存の全てのプロパティのconfigurable属性及びwritable属性をfalseにします。

  • 拡張不可能よりつよい封印よりつよい凍結
  • Object.isFrozen

おわり 2021/11/28 0:31 9m

十一章第九回 strictモード

https://uhyohyo.net/javascript/11_9.html

  • strictモードもES5から
  • 厳格モード超推進派なuhyoさん (ここまでの講座でそういう面があまり見えなかったのが不思議な感じ)
  • "use strict"; しってる
  • script タグはしらんかった
  • カンイウスコープも可能
  • function foo(){ "use strict";
  • strictモードでは、varを使わずに変数を作ることはできません。 - 知らなかった

  • グローバルスコープでvarでつくってね
  • 変数名ミスをふせげるよ
  • argumentsですが、これは実はかなり曲者なオブジェクトで、その特殊な挙動はまさに闇と呼ぶにふさわしいものです。strictモードでは、argumentsのそのような特殊な挙動がなくなります。argumentsの闇に依存してしまうといけないのでこの講座ではそういったものを紹介していませんでしたが、もし興味がある人は調べてみるとよいでしょう(しかし利用してはいけません)。

  • strictモード内ではwith文という文を使うのは禁止されています。この講座ではwith文は紹介していませんので、気になる方は調べてみましょう。。。with文を禁止することで、javascriptをより最適化することができるそうです。

  • なんか見かける気がする with
  • 使わないように使用!
  • 以外と strict モードのやってることは少なかった 2021/11/28 1:54 11m

終わり2021/11/28 1:56 13m

時間まとめ

  • 11/23 - 11/28の 6日間
    • 31 + 40 + 24 + 40 + 15 + 14 + 14 + 24 (ブログ) = 202分
    • 一回あたり 20min だ
  • 途中で 業務のTypeScript化の話をちょろっと書いた (10分)

全体の時間まとめ

  • あと残ってる回が、7 + 4 + 5 + 5 + 22 + 7 + 1 = 51 回ある 1節10分なら 510分。 実は 1日1時間なら 9日で終わる。
    • 実際には1節 20分で 1020分(17時間)では?
  • ここまでは 6 + 4 + 14 + 6 + 3 + 3 + 3 + 6 + 4 + 8 + 4 + 9 = 70 回 1節10ふんなら 700分
    • 実際には1節 20分で 1400分(23時間)では?
  • ちゃんと足してみた
    • 累計: 1114分 (= 18.6時間)
      • 一回あたり 15.9分だった
      • なので、あと 811分、 13.5時間で終わるだろう。
  • 全部で 121回。 70/121 = 58%おわった
    • 確かにマダまだ知らないことがあるね 2021/11/28 0:35 13m