最近Kindle50%ポイント還元セールがやっているみたい。最近はWeb漫画やWeb小説をひたすら読んでたり、読書をするといってもどちらかというと専門よりの本を読んでいたりと、趣味の読書をあんまりしていなかったなあと思ったので、これを機会に新書とか小説をいろいろ買ってみた。大学生の時は本屋に行って、ひたすら新書コーナーと小説コーナーをめぐって、目についたものを全部買うということをやってたけど、久々にそういうのをやった気分。読むもの困らなそうで嬉しい。順に読んでいきたい。
React触ってみた
https://facebook.github.io/react/docs/tutorial-ja-JP.html を見ながらReactをとりあえず触ってみたのでメモ。
コンポーネントを作る
コンポーネントを作って、そのrenderメソッドでどういう構造を描画するかJSXで記述しておいて、描画を変更したい時にstateを変えると、いい感じに描画してくれる、というだけっぽかった。
例えば指定した時間ごとにカウントアップするコンポーネントを作るとすると、以下の様に書いたらいい。
var CountUp = React.createClass({ getInitialState: function () { // 初期状態を定義 return { count: 0 }; }, componentDidMount: function () { // コンポーネントが最初にレンダリングされた後に実行される // 渡されたintervalミリ秒ごとにincrementメソッドを呼ぶだけ setInterval(this.increment, this.props.interval); }, render: function () { // 描画する構造の定義 return ( <span className="countUp">{this.state.count}</span> ); }, increment: function () { var count = this.state.count; this.setState({ count: count + 1 }); } }); ReactDOM.render( // CountUpコンポーネントが1000msごとにcountupするように1000を渡している <CountUp interval={1000} />, document.getElementById('content') );
あとは単にコンポーネントはネストできるからいい感じにしてください、ってだけみたい。自分で構造をどんどん弄る必要がなくて楽ですね。
親コンポーネントと子コンポーネントのデータの受け渡し
親コンポーネント -> 子コンポーネントへはプロパティっぽく渡すとデータを受けわたせる
<CountUp interval={1000} />
こんな感じで渡すと、子コンポーネントの中で、this.props.intervalが取れるだけ。
子コンポーネント -> 親コンポーネントにデータを渡す時も同じ仕組みしか使ってなさそう。親コンポーネントから子コンポーネントにcallbackのメソッドを渡して、子コンポーネントからそれを呼ぶだけ。この辺はチュートリアルを見るとわかりやすそう。
setIntervalにthis.incrementを渡してなんで大丈夫なのか
チュートリアル通りにやっていて、疑問に思ったのが、createClassのfunction内で以下のように書いてなんでうまくいくのかというところだった。
setInterval(this.increment, 1000);
普通に考えるとsetIntervalにfunctionを渡すと、そのfunction内のthisはglobalオブジェクトになりそうだけどなんでならないのか。コードを追いかけると、createClassは内部的に自動で関数をbindしてくれているみたい。
- mixSpecIntoComponentにcreateClassに渡したオブジェクトが渡されて
- React用でない関数shouldAutoBindフラグが立って
- __reactAutoBindPairsというところに入れられて
- bindAutoBindMethodsが呼ばれて
- それぞれbindAutoBindMethodが呼ばれて
- メソッドがbindされる
また、https://github.com/facebook/react/blob/38900cc7cad8906c19515c78fd082637c2046fbd/src/isomorphic/classic/class/ReactClass.js#L492 を見ると、autobindプロパティfalseを渡すとこの挙動をなくすことができるので、先ほどのコードはこうも書ける。
var CountUp = React.createClass({ getInitialState: function () { // 初期状態を定義 return { count: 0 }; }, componentDidMount: function () { // コンポーネントが最初にレンダリングされた後に実行される // 渡されたintervalミリ秒ごとにincrementメソッドを呼ぶだけ setInterval(this.increment.bind(this), this.props.interval); }, render: function () { // 描画の定義 return ( <span className="countUp">{this.state.count}</span> ); }, increment: function () { var count = this.state.count; this.setState({ count: count + 1 }); }, autobind: false });
オブジェクト指向入門 第7章〜第10章を読んだ
- 「第7章 静的な構造:クラス」
- 「第8章 実行時の構造:オブジェクト」
- 「第9章 メモリ管理」
- 「第10章 総称性」
を引き続き読んだ。これらの章はなんとなく重要そうなところをさらっと眺めるくらいで終わった。個人的にはオブジェクト指向を考える上ではクラス、オブジェクト、総称性については非常に重要で基礎は学んでおいたほうが良さそうで、とはいえ9章のメモリ管理は他のガベージコレクションの本を読んだほうが良いと思った。
ちなみに1~2年前にオブジェクト指向入門を読もうとした時(この時は断念してる)は、あんまりこれらの章をさらっと理解することは出来なかった。なぜ理解できなかったかというと、今までまともにやってきたのがPerlとJavaScriptしかなく、静的型付け言語的なパラダイムをあまり理解していなかったためだった。
しかし少し前にScala入門記 - $shibayu36->blog;にあるように、Scalaの入門を軽くしたところ、大体理解できるようになっていた。やはり知識と実践は両輪という感じ。入門するとき、自分で作ってみたいものを作るのが一番だとは思うけど、もし何も思いつかない時はGitHub - hatena/Hatena-Intern-Exercise2015: はてなインターン参加者向けの事前課題ですの課題をやってみると非常にためになるのでおすすめ。PerlとJSとScala用ではあるけど、別の言語でも同じように実践できると思う。