経験は何よりも饒舌

10年後に真価を発揮するかもしれないブログ 

Reactのコードを読む(1)

この前jQueryのコードを読んでなんとなくコードリーディングがわかってきたので今回はReactのコードを読んでいこうと思う。
wafuwafu13.hatenadiary.com

直近の目標は、以下のコードでどのようにして画面にhello worldが表示されるかを解明することである。

<!DOCTYPE html>
<html>
<head>
    <script src="https://unpkg.com/react@17/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/babel-standalone/6.26.0/babel.js"></script>
</head>
<body>
<div id="root">
</div>
<script type="text/babel">
    ReactDOM.render(
        <h1>hello world</h1>,
        document.getElementById('root')
    );
</script>
</body>
</html>

コードは今回も行数がわかりやすいようにGitHubにあげた。
github.com


まずは、ReactDOMが何なのかから見ていこうと思う。

<!DOCTYPE html>
<html>
<head>
    <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
</head>
<body>
<div id="root">
</div>
<script>
    console.log(ReactDOM)
</script>
</body>
</html>

このコードの出力結果は、以下のようなエラーである。

Uncaught TypeError: Cannot read property '__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED' of undefined
    at react-dom.development.js:15
    at react-dom.development.js:12
    at react-dom.development.js:13

react-dom.development.jsの15行目を見てみると、以下のような記述がある。
https://github.com/wafuwafu13/react-17-react-dom-17/blob/master/react-dom.development.js#L15

var ReactSharedInternals = React.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;

この__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIREDは、react.development.jsの3533行目でエクスポートされている。
https://github.com/wafuwafu13/react-17-react-dom-17/blob/master/react.development.js#L3533

exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = ReactSharedInternals$1;

よって、react.development.jsも読み込まないといけない。

<!DOCTYPE html>
<html>
<head>
    <script src="https://unpkg.com/react@17/umd/react.development.js"></script>
    <script src="https://unpkg.com/react-dom@17/umd/react-dom.development.js"></script>
</head>
<body>
<div id="root">
</div>
<script>
    console.log(ReactDOM)
</script>
</body>
</html>

今回の出力結果は、以下のようになる。

▽{__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: {…}, createPortal: ƒ, findDOMNode: ƒ, flushSync: ƒ, hydrate: ƒ, …}
 ▷createPortal: ƒ createPortal$1(children, container)
 ▷findDOMNode: ƒ findDOMNode(componentOrElement)
 ▷flushSync: ƒ flushSync(fn, a)
 ▷hydrate: ƒ hydrate(element, container, callback)
 ▷render: ƒ render(element, container, callback)
 ▷unmountComponentAtNode: ƒ unmountComponentAtNode(container)
 ▷unstable_batchedUpdates: ƒ batchedUpdates$1(fn, a)
 ▷unstable_createPortal: ƒ unstable_createPortal(children, container)
 ▷unstable_renderSubtreeIntoContainer: ƒ renderSubtreeIntoContainer(parentComponent, element, containerNode, callback)
 ▷version: "17.0.1"
 ▷__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED: {Events: Array(7)}
 ▷__proto__: Object

これらは、react-dom.development.jsの26280~26290行目でエクスポートされている。
https://github.com/wafuwafu13/react-17-react-dom-17/blob/master/react-dom.development.js#L26280

exports.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = Internals;
...
exports.render = render;
...

次回から、このrender関数について見ていこうと思う。

Linuxを購入

のが届いた。Macの5倍厚い。1万5000円。Ubuntu 16.04。

前からこういう本をやりたかったけど、Macだと仮想環境を用意しないといけない。

ルーター自作でわかるパケットの流れ

ルーター自作でわかるパケットの流れ

  • 作者:小俣 光之
  • 発売日: 2011/07/09
  • メディア: 単行本(ソフトカバー)

その仮想環境がそもそもどう構築されているのか分からないし、慣れていない仮想環境で理解できる自信がなかったので、買った方が早いと思った。
あとなんとなくLinuxに慣れたいというのもあった。ついでにvimも。

上の本をやる前に、まずこれをやりはじめた。

[試して理解]Linuxのしくみ ~実験と図解で学ぶOSとハードウェアの基礎知識

[試して理解]Linuxのしくみ ~実験と図解で学ぶOSとハードウェアの基礎知識

  • 作者:武内 覚
  • 発売日: 2018/02/23
  • メディア: 単行本(ソフトカバー)

かわいい表紙をしているが、中身はがっつりしている。

jQueryはいかにしてDOMを取得するか(3)

wafuwafu13.hatenadiary.com

いよいよ今回は、以下のHTMLを用意して実際にDOMを取得していく。

<!DOCTYPE html>
<html>
<head>
    <script src="https://code.jquery.com/jquery-3.5.1.js"></script>
</head>
<body>
<h1 id="hello">hello world</h1>
<script>
    console.log($('#hello'))
</script>
</body>
</html>

まずは前回と同じように、3133行目に定義されている関数の引数に何が入っているのかを調べる。
https://github.com/wafuwafu13/jquery-3.5.1/blob/master/jquery-3.5.1.js#L3133

jQuery.fn.init = function( selector, context, root ) {...

すると、selector"#hello"であり、contextrootundefinedであった。

よって、selectorはstring型であるため、3146行目の条件式はtrueになる。
https://github.com/wafuwafu13/jquery-3.5.1/blob/master/jquery-3.5.1.js#L3146

if ( typeof selector === "string" )

次の3147行目の条件式は、selector[ 0 ]#であるため、falseである。
https://github.com/wafuwafu13/jquery-3.5.1/blob/master/jquery-3.5.1.js#L3147

if ( selector[ 0 ] === "<" &&
...

続く3155行目で、変数matchに値が代入されている。
https://github.com/wafuwafu13/jquery-3.5.1/blob/master/jquery-3.5.1.js#L3155

match = rquickExpr.exec( selector );

ここで使われているrquickExprは、3131行目で定義されているRegExpである。
https://github.com/wafuwafu13/jquery-3.5.1/blob/master/jquery-3.5.1.js#L3131

rquickExpr = /^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,

そして、RegExp.prototype.exec()を用い、結果として以下のような配列を返し、変数matchに代入されている。

["#hello", undefined, "hello", index: 0, input: "#hello", groups: undefined]

よって、3159行目の条件式はtrueになる。
https://github.com/wafuwafu13/jquery-3.5.1/blob/master/jquery-3.5.1.js#L3159

if ( match && ( match[ 1 ] || !context ) ) {

match[1]undefinedであるため、3162行目の条件式はfalseである。
https://github.com/wafuwafu13/jquery-3.5.1/blob/master/jquery-3.5.1.js#L3162

if ( match[ 1 ] ) {

続く3192行目で、Document.getElementById()によりDOMが取得されている。
https://github.com/wafuwafu13/jquery-3.5.1/blob/master/jquery-3.5.1.js#L3192

elem = document.getElementById( match[ 2 ] );

document.getElementById("hello")の返り値はElementオブジェクトであり、以下のような値である。

h1#hello {align: "", title: "", lang: "", translate: true, dir: "", …},

続く3194行目からは、前回と同じ処理がなされている。
https://github.com/wafuwafu13/jquery-3.5.1/blob/master/jquery-3.5.1.js#L3194

if ( elem ) {

    // Inject the element directly into the jQuery object
    this[ 0 ] = elem;
    this.length = 1;
}
return this;

よって、console.log($('#hello'))で以下の値が得られた。

▽jQuery.fn.init [h1#hello]
 ▷0: h1#hello
    length: 1
 ▷__proto__: Object(0)

今回でjQueryはいかにしてDOMを取得するかが解明できた。
次は違うコードを読んでいきたい。

jQueryはいかにしてDOMを取得するか(2)

wafuwafu13.hatenadiary.com

前回は、以下のHTMLを用意し、

<!DOCTYPE html>
<html>
<head>
    <script src="https://code.jquery.com/jquery-3.5.1.js"></script>
</head>
<body>
<script>
    console.log($);
</script>
</body>
</html>

以下の実行結果を得た。

ƒ ( selector, context ) {

		// The jQuery object is actually just the init constructor 'enhanced'
		// Need init if jQuery is called (just allow error to be thrown if not included)
		return new jQuery…

これは、153行目で定義されている定数であった。
https://github.com/wafuwafu13/jquery-3.5.1/blob/master/jquery-3.5.1.js#L153

今回は、console.log($())とすることで、関数の実行結果、つまり157行目の、
https://github.com/wafuwafu13/jquery-3.5.1/blob/master/jquery-3.5.1.js#L157

jQuery.fn.init( selector, context )

の実行結果を見ていきたい。

関数は、3133行目に定義されている。
https://github.com/wafuwafu13/jquery-3.5.1/blob/master/jquery-3.5.1.js#L3133

jQuery.fn.init = function( selector, context, root ) {...

ここで、引数であるselectorcontextrootには何が入っているのかを調べると、
selectorは、

#document {location: Location, implementation: DOMImplementation, URL: "file:///Users/tagawahirotaka/Desktop/index.html",....

であり、contextrootundefinedであった。

よって、selectorは、Documentであることがわかる。

selectorが未定義ではなく、string型でもないため、3137行目と3146行目の条件分岐はスルーされる。
https://github.com/wafuwafu13/jquery-3.5.1/blob/master/jquery-3.5.1.js#L3137
https://github.com/wafuwafu13/jquery-3.5.1/blob/master/jquery-3.5.1.js#L3146

if ( !selector )
...
if ( typeof selector === "string" )


続く3214行目には以下のような条件分岐がある。
https://github.com/wafuwafu13/jquery-3.5.1/blob/master/jquery-3.5.1.js#L3214

else if ( selector.nodeType )

selector.nodeTypeを調べてみると、値は9であった。

DocumentNodeを継承しており、Node.nodeType9は、DOCUMENT_NODEを意味している。

この3215行目からの条件分岐内で、以下のような処理がなされる。
https://github.com/wafuwafu13/jquery-3.5.1/blob/master/jquery-3.5.1.js#L3215

this[ 0 ] = selector;
this.length = 1;
return this;

thisjQuery.fn.initのことで、そこにselectorが挿入されている。

f:id:wafuwafu13:20201122152339p:plain

しかし、console.log($())の出力を見てみると、

▽jQuery.fn.init {}
  ▷__proto__: Object(0)

となっているため、後続の処理で破棄されている。

ちなみに、thisjQuery.fn.initである理由は、生成されるインスタンス自身がthisにセットされるからである。

function foo() {
    console.log(this) // ▽ foo {}
                //  ▷ __proto__: Object
}

var bar = new foo()


wafuwafu13.hatenadiary.com

jQueryはいかにしてDOMを取得するか(1)

最近、バイトの隙間時間に、jQueryを廃止してTypeScriptにリプレイスする、というタスクをするようになった。
jQueryのDOMの取得を、Documentを使って書き換える時に、jQueryはいかにしてDOMを取得するか、ということが気になったので少し調べていく。

今回は、そもそもjQuery$はなんなのか、ということを調べた。
jQueryのコードは、https://code.jquery.com/jquery-3.5.1.jsから入手し、行数を分かりやすくするためにここに置いた
github.com

さっそく、以下のHTMLを用意して、コードを見ていく。

<!DOCTYPE html>
<html>
<head>
    <script src="https://code.jquery.com/jquery-3.5.1.js"></script>
</head>
<body>
<script>
    console.log($);
</script>
</body>
</html>

このコードの実行結果は、以下のようになる。

ƒ ( selector, context ) {

		// The jQuery object is actually just the init constructor 'enhanced'
		// Need init if jQuery is called (just allow error to be thrown if not included)
		return new jQuery…

この実行結果は、153行目で定義されている。
https://github.com/wafuwafu13/jquery-3.5.1/blob/master/jquery-3.5.1.js#L153

// Define a local copy of jQuery
jQuery = function( selector, context ) {

    // The jQuery object is actually just the init constructor 'enhanced'
    // Need init if jQuery is called (just allow error to be thrown if not included)
    return new jQuery.fn.init( selector, context );
};

実際に返されている部分は、最後の10871行目である。
https://github.com/wafuwafu13/jquery-3.5.1/blob/master/jquery-3.5.1.js#L10871

return jQuery;

これがなぜconsole.log($);で出力できるかというと、10865行目に以下のような処理をされているからである。
https://github.com/wafuwafu13/jquery-3.5.1/blob/master/jquery-3.5.1.js#L10865

window.jQuery = window.$ = jQuery;

だから、console.log(jQuery);としても同じ結果が得られる。

wafuwafu13.hatenadiary.com

得意は相対的な概念だった

得意なことを複数人の前で挙げる機会があってはじめて気がついてショックを受けた
社会学部にいたら得意はプログラミングだが、その場ではなにもなかった
0->8を繰り返していきたい - 経験は何よりも饒舌
こんなことを書いていたが、よく考えれば8も相対的でその場では0だった
0->8を並行的に繰り返していたと思っていたが、直列の0->8->0->8->.... のループを繰り返しているのかもしれない
それなら絶対的な得意、絶対的な10を1つ得れれば良いのだが、それを求めるにははじめるのが遅すぎた
と考えると同時に、絶対的な10が、宇宙1になるしか得れないものだとしたら、虚像を求める終わりなき闘争をはじめてしまっているのかもしれない
さっき挙げた並列も、得意という大枠で捉えたらギュッとまとめられて直列になってしまう
何かに夢中になれるのが羨ましいと言ってくれた人がいるが、それが限りなく真なのかもしれない

サビで体言を断言する歌

こういう歌が増えて欲しい
他の歌が必要なくなってしまうけど

それを言葉という

www.youtube.com

「言葉にすればたやすくて」って言葉にしなきゃ分かんねぇよ
君は伝える事諦めてはだめだ それを届けて
死に損なった朝が眩しい 出掛けさせられてる毎日に
千切れた涙を銃弾としてこめろ それを言葉という

古いSF映画

www.youtube.com

僕らが信じる真実は 誰かの創作かもしれない
僕らが見てるこの世界は 誰かの悪意かもしれない
人が人である理由が 人の中にしかないのなら
明け渡してはいけない場所 それを心と呼ぶんでしょ

瞬き

www.youtube.com

幸せとは 星が降る夜と眩しい朝が
繰り返すようなものじゃなく
大切な人に降りかかった雨に傘を差せる事だ