{...obj} は null でも大丈夫
{...obj}

ってかなり便利で既存のオブジェクトに代入したいとき以外は Object.assign は使わず基本こっち

だけど obj がオブジェクト以外だと問題起きそうで null とか来そうなら Object.assign にしたり

{...(obj || {})}

とかやってました
だけどそんなことしなくても null でもエラーなりませんでした

{...null}
// {}
{...undefined}
// {}
{...false}
// {}
{...123}
// {}
{..."abc"}
// {0: "a", 1: "b", 2: "c"}
{...[10, 20]}
// {0: 10, 1: 20}

false や 123 などもオブジェクトじゃないならなにもせず空のオブジェクトになります
ただ 文字列や配列の場合はインデックスをキーとしてオブジェクト扱いされます

ちなみに配列の場合は

;[...null]
// Uncaught TypeError: null is not iterable

数値などでも iterable じゃないものはすべてエラーになります

pax という Rust 製 JavaScript バンドラーを見つけた
JavaScript のバンドラーというと

◯ webpack
◯ parcel
◯ rollup

くらいだろうと思ってたらこんなのをみつけた

https://github.com/nathan/pax

JavaScript じゃなくて Rust で作られてるみたい
バンドラーって基本 Babel みたいなトランスパイルや UglifyJS みたいなミニファイツールを使うし それらは基本 JavaScript で作られてるからバンドラーも JavaScript だと思ってけど Rust らしい
そういうの全部含んでる大規模なプロジェクトには見えないし どういうものなのか軽くみただけだとよくわからない

少し気になったところがあって 前の名前が 「parcel redux」 で略して 「pax」 らしい
https://github.com/nathan/pax/commit/ae70ce4a5370bbfcd5395b287f4595e10b9b98f5

内部で parcel 使ってて Rust はただのラッパーと考えたけど それだと直接 parcel 使うのより遅そうだしあんまりメリットがない
速度は早いらしいし たまたま名前かぶっただけであの parcel とは関係ないのかな?
もうひとつの redux の方はフロントエンドの状態管理ライブラリなわけでバンドルには関係なさそうだし
node-dev マウント環境で使えない
サーバ側の Node.js でも変更監視してリロードできると聞いて node-dev を入れてみたけど動かなかった
基本 実ファイルは Windows で動かすための Linux 環境はそこを mount してるから監視系ツールは使えないの多め

フロントエンドの parcel の watch は結局 Windows 側でしてるし

cifs マウント可能性高そうな VirtualBox のマウントだったけどやっぱりダメだった
監視するツールが動く OS で管理してるファイルシステムじゃないと無理っぽいね

Node.js のプロセス管理ツールの PM2 でも watch できるみたいだけどたぶんこれも動かないと思う
hyperHTML でカスタムイベントをリッスンする
on から始まると以降をイベント名としてリスナ扱いになる
「-」 や 「_」 があっても気にせず on*** にすればいい

customElements.define("x-elem", class extends HTMLElement {
constructor(){
super()
this.attachShadow({mode: "open"})
this.render()
}

render(){
bind(this.shadowRoot)`
<div
onxxx=${eve => console.log("event xxx")}
onx-x=${eve => console.log("event x-x")}
onx_x=${eve => console.log("event x_x")}
>
<button onclick=${
eve => {
eve.target.dispatchEvent(new Event("xxx", {bubbles: true}))
eve.target.dispatchEvent(new Event("x-x", {bubbles: true}))
eve.target.dispatchEvent(new Event("x_x", {bubbles: true}))
}
}>event</button>
</div>
`
}
})

on が最初の区切りまでとくっついて見づらいので 区切り文字は使わず全部小文字にしたほうがいいのかも

注意するところは大文字小文字を同一視したときに同じ名前は別々に設定できないこと

<div
onxxx=${eve => console.log("event xxx")}
onxXx=${eve => console.log("event xXx")}
></div>

これは無効
hyperHTML 内部でエラーが起きる

原因は

document.body.innerHTML = `<div a="1" A="2" b="3"></div>`
document.body.innerHTML
// "<div a="1" b="3"></div>"

HTML 自体が大文字小文字を区別しないで 同じ属性をふたつ作れないから

後のほうは消される
消された結果 属性と埋め込み値の数が合わなくてエラーになる
Dart2 やっぱり使わないかな
Dart2 がリリースされたとかいうのを少し前に聞いたので見てみました
Flutter とかモバイル系向けになった?みたいだけど JavaScript の置き換えはやめたのかな?

軽くみてみた感じは C 系をベースにした言語と大差ない感じの構文
var や const にもできるけど型指定あり
しかもここも C 系みたいな書き方

String name = 'Bob';

Future<String> lookUpVersion() async => '1.0.0';

void main() {
assert(sort is Compare<int>); // True!
}

私としては型指定とかメタデータ的なのはアノテーションみたいなコードの外部に置いてほしいんですよね
最近の型あり言語の仕様を見ては毎回書いてる気がしますが elm (Haskell) 的な型指定の見た目が好きで 型指定の有無は別の行に独立させて変数の宣言代入処理とは切り離してほしいです
変数名や関数定義の前に長い型名とかあると見づらいだけです

流し見程度なのでよくわかってませんが型付けできる altJS としてなら TypeScript で良くない?というところ
そういえば前に Android 代替 OS が Dart とか噂を聞いた気がしますし そういう別方面の言語になればいいと思います
なんにせよあんまり使ってみたいと思えないものでした
一見問題なさそうに見える
if [x == y]:
print(1)
else:
print(0)

何がおかしいんだろうと思ったけどこれは絶対 1 が表示される
[] は比較条件を書くところじゃなくてただの配列
Python は配列に要素が 1 つでもあったら True になる
比較結果の boolean 値があるので常に True の場合の分岐になる
Hack は using + disposable を使うらしい
少し前に Hack がいろいろ変わって PHP の悪いところ切り捨てていくみたい とかいう話を聞いてしばらくしたのでなにか変わってるのかなと見てみると……
もう 少し前の話みたいですがデストラクタが廃止されて using+disposable 使うようになったみたいですね

この組み合わせ C# ぽいですね (C# にはデストラクタもありますけど

IDisposable を継承したクラスで __dispose メソッドを実装して

class Handle implements \IDisposable {
public function __dispose(): void {}
public function foo(): void {}
}

using を使って そのクラスのコンストラクタを呼び出します

using ($x = new Handle()) {
$x->foo();
}

基本は C# と一緒

ただ関数スコープもできるみたいで

using new Handle();

と書いたらそのスコープが終わってから __dispose が呼び出されるようです

PHP もこうすればいいのに
そろそろライブラリは ShadowDOM を考慮してほしい
JavaScript のライブラリで ShadowDOM 考慮されてないのが多い
全部の要素が document からつながってる前提 クエリセレクタで取ってこれる前提
そんなのが多すぎ

そろそろ WebComponents を意識したのが増えてきてほしい
WebComponents 使ってたら body 以下って xxx-app みたいなタグ一つだけでほかは全部その app の ShadowDOM の中ってことが普通にある
だからこれまでの DOM 構造を前提としてたら何もできないようなものもありうる


jQuery は一応親指定できるけど基本 document からだし WebComponents で作るなら使わないのが基本になってくれるといいなぁ
使いたい人が勝手に使う分には別にいいんだけど 割と良さそうなライブラリがあってそれが jQuery 必要とか書いてるとすごく嫌な気分になるから
結局 jQuery 入れるくらいなら自分で作ると言って自作ツールが増えてる……
正規表現の */ が地味に迷惑
function a(str) {
const reg = /\d*/g
return reg.test(str)
}

こんな感じのコードがあってまとめてコメントアウトしたいから /**/ で囲んだのになんかエラーでてる
確認してみたら 正規表現の */ でコメントが終わってて それ以降が JavaScript として扱われて構文エラー

正規表現リテラルが 「/」 なの地味に困る

ブロックコメントのネスト機能もないし その行の最初に // 入れてもコメント中なら無意味だし */ の後に入れたらコードの途中だからコメントアウトを外すとき辛いし
ブロックコメントは使わず矩形選択してブロックコメント化したいところ全行の最初に // 入れるのが良いのかな
Promise の回収
Node.js でこれを実行したら 1 秒後に 1 を表示して Node.js のプロセス自体が終了する

function a(){
return new Promise(resolve => {
setTimeout(() => {
console.log(1)
return 2
}, 1000)
})
}

function rec(){
a().then(e => rec())
}

rec()

ずっと繰り返されそうにと思ってたけど Promise 内で resolve を使わず return してた
こういう resolve も reject もせず放置された Promise ってちゃんと回収されるのかなんか不安があったけどちゃんと回収されてるみたいで安心

ところで return 2 を resolve(2) に直すと毎秒 1 がで続ける
2 には特に意味はない

今回のだと絶対に resolve も reject もされないってわかるからであって fetch したときにサーバが end 忘れててレスポンスが永遠に来ないとかだとダメだと思う
そういうことはあまりなさそうだけど WebSocket のライブラリで socket に対してレスポンスを返せるもので返し忘れはわりとありそうな気はする
関数をクローンしたいとき
オブジェクトをディープクローンするとき 中に関数があるとどうするか困るのが関数
プリミティブ値はそのままで 配列とオブジェクトはプロパティを再帰的にコピーでなんとかできる
でも関数はどうするのがいいかベストな方法がわからない

考えられるのは

◯ そのまま
◯ 文字列から再作成
◯ 元関数を通すだけの関数を作る

関数自体の機能はイミュータブルなのでそのまま参照をコピーするだけで基本は大丈夫
でもオブジェクトだからプロパティがあって それが使われてる場合はクローン後の関数のプロパティを書き換えたら元の関数のプロパティも変わってしまう

ちゃんとクローンするなら toString の文字列を元に eval などで再作成
パフォーマンスが悪そうなのと静的スコープが維持されないので外部を参照してると動かなくなるなど問題もある

だから新しく同じ処理をする関数を作るのじゃなくて クローン元の関数を実行するという関数を作る
プロパティを引き継ぐために プロパティだけは通常のオブジェクトと同じようにクローンする
呼び出しの階層が 1 つ深くなるくらいしかデメリットもないし ちゃんとクローンするのならこの方法が一番いいのかな
条件演算子とスプレッド演算子
フラグによって引数を変えたいときで 引数の数も変わるとき

console.log(true ? ...[1, 2] : 3)

って書いてみて なんかおかしい気が
「...」 って引数のところに使える構文で式ではないはず
エラーになりそう

やってみるとやっぱり
「Unexpected token ...」

正しいやり方は?


単純にやるなら

true ? console.log(...[1, 2]) : console.log(3)

if 文で関数呼び出しを 2 回書きたくないから ?: つかってるのに結局 2 回書いてる
console.log 程度ならいいけどここが長いと書くの大変

まとめるなら引数に 「...」 を使うのは確定させて 「...」 のあとの式を ?: で書く

console.log(...(true ? [1, 2] : [3]))
for-of でオブジェクトを使いたい
for-of は便利ですが オブジェクト型の場合はそのまま使えません

for(const item of [1, 2, 3]){
console.log(item)
}
// 1
// 2
// 3

for(const item of {a: 1, b: 2}){
console.log(item)
}
// error
// オブジェクトが iterable じゃないと言われる

Object.entries を通せば

for(const item of Object.entries({a: 1, b: 2})){
console.log(item)
}
// ["a", 1]
// ["b", 2]

でも毎回は面倒です
そこで

Object.prototype[Symbol.iterator] = function*(){ yield* Object.entries(this) }

を用意しておくと

for(const item of {a: 1, b: 2}){
console.log(item)
}
// ["a", 1]
// ["b", 2]

どうしてこれがデフォルトで設定されていないのかな

parcel 1n もダメだった
bigint の 1n も parcel で使えなかった
ブラウザで使えるのしか使わないから babel の変換通さずモジュール解決だけでしてそのまま出力してくれないのかなー
この制限が邪魔すぎる

使えないところを文字列にして

const a = WILLREPLACE`1n`
const b = WILLREPLACE`{...obj}`

これでバンドルして バンドル済みファイルを

js.replace(/WILLREPLACE`(.+?)`/g, "$1")

で置換して使うとか考え始めた

build だといいけど watch とかだと変換通すのが難しいかも
service worker 使えばソースコード改変できるんだっけ?
できても service worker 使うのは https 必要かぁ

いっそのことバンドルしなくて良いんじゃないかと思い始めた