t_hazawaの日記

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

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

JavaScript中級者になろう 10章を読んだ(XPath)

前: JavaScript中級者になろう 9章を読んだ(オブジェクト志向) - t_hazawaの日記

経緯

  • 業務システムをTypeScriptにする構想を練った
  • 息抜きがてら中級者

第十章 XPath

十章第一回 XPathとは

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

  • xpathcssセレクタよりも数段強力な表現力をもちます

  • xpathには「現在のノード」という概念があります

  • 僕はこのことを認識してなかった
  • スラッシュ(/)に続けて要素名を書く構文は、子ノードへの移動を意味します

  • body要素の子に複数のp要素がある場合どれが当てはまるかというと、全部です このように、現在のノードが複数となることもあります。

  • 軸 :: ノードテスト

  • *は全ての要素ノードを意味するノードテストであり、テキストノードなどその他のノードは含みません

  • /html/body/child::text()

  • /html/body/descendant::text()と書けば、body要素内の全てのテキストノードのノードセットとなり、webページのテキストが全て集まるでしょう - ☆すごく便利そう

  • node()(全ての種類のノード)

  • /html/body//とすると、body要素を含めてそれ以下の要素全部のノードセットが結果

  • /html/body//self::p。。これは「body要素中のp要素全て」

  • /html/body/descendant-or-self:p と同じ

十章第二回 DOMでのXPathの利用

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

  • XPathを実際に使ってみよう
  • documentが持つevaluateというメソッド これは、5個の引数を渡してxpathを処理してもらい、結果をxpathresultというオブジェクトで返すものです

  • 引数ooi
  • ルートノードもわたせるよ
  • 第三引数は 名前空間解決器 (かっこいい) xml よう
  • XPathResult.FIRST_ORDERED_NODE_TYPE

  • iterateNext は木構造が変わるとエラー

十章第三回 属性の取得と型

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

  • /attribute:: だと、現在nodeの属性を調べるぞ
  • nodeTypeプロパティを持ち、しかもNode.ATTRIBUTE_NODEという定数で示される種類のノードであることが分かります。これが属性ノードです。なお、属性ノードの正式名称はAttrといいます。

  • 属性ノードというものがアンんだね
  • zokuseiNode.value で lang属性の値である "en" がとれる
  • attrノードが使われることは多くありません

  • xpathは文字列や数値・真偽値も扱うことができます xpathの型は真偽値型、数値型、文字列型、そしてノードセット型の4つです。

  • string(/html/attribute::lang)
  • XPathには関数がある
  • 実は属性ノードは文字列に変換すると属性の値に変換されます。

  • attribute軸を@で省略できるというものです。すなわち、 /html/attribute::lang を /html/@lang と書けます。

十章第四回 述語による絞り込み

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

  • 述語(Predicates)

  • ノードテストによる絞り込みでは不十分で、もっと細かい条件を指定したい場合もあることでしょう。そういったときに使うのが述語です。

  • 述語の書き方は、/html/body/child::p[1]のように[]で囲んだ式をくっつけます

  • /html/body/p[last()]

  • /html/body/p[position()<=2]

  • /html/body/p[1]は/html/body/p[position()=1]の省略形
  • /html/body/descendant::p[attribute::lang="ja"]
  • 要素ノードなど木構造中に存在するノードを文字列に変換するときには、その子孫のテキストノードを全て連結した値になります。

  • /html/body/descendant::p[ancestor-or-self::*/@lang="ja"]
  • /html/body/p[@lang="ja"][last()]。。まず、ノードテストでbodyの子のpに絞りこまれ、次の述語でlang属性が"ja"のものに絞りこまれ、その次の述語で、絞りこまれたp要素のうち最後のp要素になります

時間まとめ

  • 2021/11/20-21
  • 15+22+18 + ブログ6分 = 61分
  • 累計 : 912分

次回

  • 次からはいよいよES2015 (楽しみ)

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