クリーンアーキテクチャを読んだ
2021/08/19 02:19
読書
[クリーンアーキテクチャ](https://www.amazon.co.jp/Clean-Architecture-%E9%81%94%E4%BA%BA%E3%81%AB%E5%AD%A6%E3%81%B6%E3%82%BD%E3%83%95%E3%83%88%E3%82%A6%E3%82%A7%E3%82%A2%E3%81%AE%E6%A7%8B%E9%80%A0%E3%81%A8%E8%A8%AD%E8%A8%88-Robert-C-Martin/dp/4048930656)を読んだのでメモとして残す。 ただし、所々省略していたりそもそもメモってない箇所もあるので悪しからず。 ## 一部 **1章** - ソフトウェアアーキテクチャの目的は「求められるシステムを構築・保守するために必要な人材を最小限に抑えること」 - 結果的に、クリーンなコードを書いた場合の最遅よりも、クリーンでないコードを書いた時の最速の方が遅くなっていく **2章** 省略 --- ## 二部 **3章** 3つのパラダイムは、それぞれ「何をすべきか」よりも「何をすべきでないか」、という意図を伝えている これらのパラダイムは、アーキテクチャの「コンポーネントの分離」「データ管理」「機能」という関心事に対応している - 構造化プログラミング - オブジェクト指向プログラミング - 関数型プログラミング **4章(構造化プログラミング)** - 反証可能(テストすることが可能)なプログラミングの単位を作成する能力が重要 - テストはバグが存在しないことは証明できず、バグが存在してることを示すものである - **機能分割** - プログラムを再帰的に分割して、証明可能な小さな機能する必要がある - 証明可能な小さな機能が正しくないことを、テストを使って証明する **5章(オブジェクト指向(OO)プログラミング)** OOとは:ポリモーフィズムを使用することで、システムにある全てのコードの依存関係を絶対的に制御する能力 --- ## 三部 SOLID原則について 目的 - 以下のような性質を持つ中間レベルのソフトウェア構造を作ること - 変更に強いこと - 理解しやすいこと - コンポーネントの基盤として、多くのソフトウェアシステムで利用できること - 中間レベル:コードレベルよりも上に適用されるもので、モジュールやコンポーネントで使うソフトウェア構造の定義に役立つ - SOLID原則 - 単一責任の原則(SRP):クラスに任せる責任は一つのみにすること - オープン・クローズドの原則(OCP):ソフトウェアのエンティティ(クラス、モジュール、関数)は拡張に対して開き、修正に対して閉じていなければならない - リスコフの置換原則(LSP):スーパークラスは、そのサブクラスで代用可能でなければならない - 要はサブクラスの型を知る必要がないようにし、サブクラス側にoverride を強制するようにしろということ - インターフェース分離の原則(ISP):クライアントが利用しないメソッドへの依存を強制してはならない - 依存性逆転の原則(DIP) - 高水準モジュールは低水準モジュールに依存してはならない。両者は、抽象化に依存するべきである。 - 抽象化は、詳細に依存してはならない。詳細は、抽象化に依存するべきである。 **7章(**単一責任の原則**)** リファクタリングとかでいう「どのモジュールも一つのことのみ行うべき」という原則とは異なる(これはリファクタリングの方の原則) **8章**(オープンクローズドの原則) - 拡張に対して開いていて、修正に対して閉じていないといけない - ちょっとした修正のために大量の書き換えが発生しないようにするのが重要 - 上位コンポーネントは、下位コンポーネントの修正に対して無関心であるべき **9章**(LSP: リスコフの置換原則) - スーパークラスとサブクラスは置換可能でないといけない - サブクラスの入力のパターンは、基本クラスの入力のパターンよりも緩い - 厳しくなってしまうと、利用者側はサブクラスを使う際に厳密な入力(引数)が求められてしまうことになる - サブクラスの出力のパターンは、基本クラスの入力のパターンよりも厳しい - 緩くなってしまうと、利用者がサブクラスの挙動について詳細を知る必要が出てきてしまう 参考: [https://qiita.com/yuki153/items/142d0d7a556cab787fad](https://qiita.com/yuki153/items/142d0d7a556cab787fad) [https://qiita.com/yuu341/items/1a45048950f3b5b76bdc](https://qiita.com/yuu341/items/1a45048950f3b5b76bdc) **10章**(ISP:インターフェース分離の原則) - クライアントは使用しないインターフェースの実装を強制されるべきではない - インターフェース実装時は、それぞれのクラスに必要な箇所のみを抽出したインターフェースを作れ、ということ 参考: [https://zenn.dev/chida/articles/882aad07effa5c](https://zenn.dev/chida/articles/882aad07effa5c) **11章**(依存関係逆転の原則) ソフトウェアの変更時は、具象の変更で収まるようにし、抽象の変更は極力しないようにするのが原則 - 変化しやすい具象クラスを参照しない - 代わりに抽象インターフェースを参照するようにすること(変更が少ないため、何らかの変更に巻き込まれて自分も修正しないといけない、ということが減る) - 変化しやすい具象クラスを継承しない - 具象関数をオーバーライドしない - 変化しやすい具象を名指しで参照しない 参考: [https://techracho.bpsinc.jp/hachi8833/2019_05_09/62314](https://techracho.bpsinc.jp/hachi8833/2019_05_09/62314) rubyの例あり [https://madogiwa0124.hatenablog.com/entry/2019/11/08/211648](https://madogiwa0124.hatenablog.com/entry/2019/11/08/211648) **12章**(コンポーネント) コンポーネントとはデプロイの単位→rubyならgemファイル インタプリタ型言語ならソースファイル **13章**(コンポーネントの凝集性) コンポーネントの凝集性に関わる3つの原則。 アーキテクトに対して以下の3つの原則をバランスよく取り入れることが重要 - 再利用・リソース投下の原則(REP)→再利用性のためのグループ化 - コンポーネントを再利用するには、コンポーネントのリリース単位で行う - 再利用の単位とリリースの単位は同じになる - 閉鎖性共通の原則(CCP)→保守性のためのグループ化 - 同じ理由、同じタイミングで変更されるクラスをコンポーネントにまとめること。 - 単一責任の原則の言い換え→コンポーネントを変更する理由が複数あるべきではない - 全再利用の原則(CRP)→不要なリリース作業を減らすための分割 - 1つのクラスのみを再利用することはほぼなく、複数のクラスと組み合わせて使われることが大半のため、そういったクラス群は1つのコンポーネントにまとめる 参考: コンポーネントに関する6つの原則(13・14章合わせて) [https://qiita.com/NagaokaKenichi/items/65c149ba92580fce5be2#全再利用の原則crpthe-common-reuse-principle](https://qiita.com/NagaokaKenichi/items/65c149ba92580fce5be2#%E5%85%A8%E5%86%8D%E5%88%A9%E7%94%A8%E3%81%AE%E5%8E%9F%E5%89%87crpthe-common-reuse-principle) **14章**(コンポーネントの結合) - 非循環依存関係の原則(ADP) - コンポーネントの依存構造に循環依存があってはいけない - 依存関係のグラフが有向非循環グラフ(循環構造が存在しない有向グラフ)で表されているか - 安定依存の原則(SDP) - 安定度の高いコンポーネントに依存するという原則 - 多数のコンポーネントから依存されたコンポーネントは変更しづらい、そのためこういったコンポーネントは安定度が高いと考えらえれる - 基本的には抽象度の高いレイヤーに依存するべきなので、安定度の高い=抽象度の高いと言い換えられる - 安定度・抽象度評価の原則(SAP) - コンポーネントの抽象度は、その安定度と同程度でなければならない - 安定度の高いコンポーネントは抽象度も高くあるべきで、安定度の高さが拡張の妨げになってはいけない - 安定度が低いことによってその内部の具体的なコードが変更しやすくなるため、安定度の低いコンポーネントはより具体的であるべき --- ## 五部 **15章(アーキテクチャとは)** アーキテクチャの形状の目的は、「できる限り長い期間、できるだけ多くの選択肢を残せるようにすること」 - 残すべき選択肢とは、重要ではない詳細のこと - **アーキテクトは、方針・詳細を区別して、方針が詳細を把握・依存することないようにする必要がある** - 方針:重要なもの、優先度高 - 詳細:重要でないもの、優先度低 - 詳細は決定を延期・留保することができる その他 - 早い段階から**デプロイ周り**の戦略を考える必要がある - アーキテクチャが優れていれば、自ずと運用方法は明確になる --- **16章(独立性)** 省略 **17章(バウンダリー)** ソフトウェアアーキテクチャに境界線を引くために、まずシステムをコンポーネントに分割する。この中のいくつかのコンポーネントがコアのビジネスルールとなる。 個人的に、DBの構成等はビジネスルールに密接に結びつくと考えていたので、DBの決定は遅らせることができる、というのは目から鱗 **18章(境界の解剖学)〜21章まで省略** **22章(クリーンアーキテクチャ)** アーキテクチャの目的 = 関心事の分離 クリーンアーキテクチャが生み出すシステムについての特性 - フレームワーク非依存 - アーキテクチャはソフトウェアのライブラリに依存しない - そのため、フレームワークに依存せず、単なるツールとして利用できる - テスト可能 - ビジネスルールはUI、データベース、webサーバ、その他の外部要素がなくてもテスト可能 - UI非依存 - ビジネスルールを変更することなく、ウェブUIをコンソールUIに置き換えることができる - データベース非依存 - どのデータベースにも置き換えることが可能 - 外部エージェント非依存 - ビジネスルールは、外界のインターフェイスについて何も知らなくていい - 下図について 円の外側は仕組み、内側は方針 アーキテクチャを動作させる重要なルールは「依存性のルール」 - ソースコードの依存性は、内側(上位レベルの方針)だけに向かっていなければならない - つまり、円の内側は外側について何も知らなくていい - エンティティ - 企業全体の最重要ビジネスルールをカプセル化したもの - ページのナビゲーションやセキュリティに変更があったとしても、エンティティが影響を受けることはない - ユースケース - アプリケーション固有のビジネスルールが含まれている - ソフトウェアが何ができるのか、を示す - ドメイン駆動設計でいうところのアプリケーションサービス - インターフェースアダプター - 入力、永続化、表示を担当するオブジェクトが所属する - 永続化とはデータの保存、表示は結果の表示を表す - 一般的な MVC フレームワークや単体テストクラスなどはこのレイヤーに所属する - フレームワークとドライバ - データベース操作オブジェクトやウェブフレームワークなど - このレイヤーではあまりコードは書かない - 境界線を越えるには - 図の右下がそれを表している - 例:ユースケースから円の内側にあるインターフェースを呼び出すようにして円の外側にあるプレゼンターを呼び出すなどする <img src="https://lh3.googleusercontent.com/d/1LQkqHUhAgz7qAt4B9F-bPsYjKu_kgJci"> - 参考: [https://gist.github.com/mpppk/609d592f25cab9312654b39f1b357c60](https://www.notion.so/609d592f25cab9312654b39f1b357c60) [https://qiita.com/nrslib/items/a5f902c4defc83bd46b8#enterprise-business-rules](https://qiita.com/nrslib/items/a5f902c4defc83bd46b8#enterprise-business-rules) [https://www.slideshare.net/AtsushiNakamura4/clean-architecture-release](https://www.slideshare.net/AtsushiNakamura4/clean-architecture-release)
ブログ作りました
2021/08/12 23:16
ブログを自作しました。 ブログ作ってみると、はてなブログがいかに完成されたサービスかよく分かります。 改善点はまだまだあるけど、ひとまずこちらを運用していこうと思っています。 それではよろしくお願いします m(_ _)m
近況について
2021/05/20 23:17
<p>こんにちは、fujjimaです。</p> <p>ブログの方は、管理画面側は終わったんで一般画面の方作ってます。 全部<a class="keyword" href="http://d.hatena.ne.jp/keyword/Rails">Rails</a>なので特殊なことは何もしてないです。月別<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%A2%A1%BC%A5%AB%A5%A4%A5%D6">アーカイブ</a>作ってみて思ったけど、あれって結構実装面倒なんだね。</p> <p>最近の近況だけ言うと、一応仕事はしています。 2ヶ月ぐらい前から仕事再開し出しました。まだ当分は今の現場で働きます。</p> 基本的に設計の議論とかをメンバー内で行うのが通例になっているので、疑問点とかをそこでシェアできるのが私的にはいいと思います。 今の現場にどれぐらいいるかは分かりませんが、在籍している間はチームの生産性に少しでも寄与できればと考えています。
近々ブログを移設します
2021/03/08 22:47
<p>そういやブログの自作をしていなかったと思い立ったので、近々自分のブログを作ってそっちに引っ越そうと思います。 今のところ全部<a class="keyword" href="http://d.hatena.ne.jp/keyword/Rails">Rails</a>で作る予定で、簡単に済ませたい。</p> <p>というか転職しないといけないんだよ、俺は。</p>
Material-UIのSelect内のテキスト部分のスタイルをいじる
2021/02/13 18:19
<h3>したいこと</h3> <p>Material-UIのSelect<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%DD%A1%BC%A5%CD%A5%F3%A5%C8">コンポーネント</a>内にあるテキスト部分のスタイルを変更したかった。 具体的には、下図のようにテキストエリアの範囲を縮小したかった。</p> <p><b>変更前</b></p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/f/fujjima/20210208/20210208121616.png" alt="f:id:fujjima:20210208121616p:plain" title="" class="hatena-fotolife" itemprop="image"></span></p> <p><b>変更後</b></p> <p><span itemscope itemtype="http://schema.org/Photograph"><img src="https://cdn-ak.f.st-hatena.com/images/fotolife/f/fujjima/20210208/20210208121722.png" alt="f:id:fujjima:20210208121722p:plain" title="" class="hatena-fotolife" itemprop="image"></span></p> <h3>タグ構造</h3> <p>Select周りの構造は下記の通りになっているとする。 今回「ここから〜ここまで」で囲まれている範囲のスタイルを変更することを目的とした。 該当部分のReact<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B3%A5%F3%A5%DD%A1%BC%A5%CD%A5%F3%A5%C8">コンポーネント</a>も記載しているが、jsx用の<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%B7%A5%F3%A5%BF%A5%C3%A5%AF%A5%B9">シンタックス</a>ハイライトを当てていないので、雰囲気でおなしゃす。</p> <pre class="code lang-html" data-lang="html" data-unlink> <span class="synIdentifier"><</span><span class="synStatement">div</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"MuiInputBase-root MuiOutlinedInput-root makeStyles-statusMenu-16"</span><span class="synIdentifier">></span> <span class="synComment"><!-- ここから --></span> <span class="synIdentifier"><</span><span class="synStatement">div</span> <span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"MuiSelect-root MuiSelect-select MuiSelect-selectMenu MuiSelect-outlined MuiInputBase-input MuiOutlinedInput-input"</span> <span class="synIdentifier"> </span><span class="synType">tabindex</span><span class="synIdentifier">=</span><span class="synConstant">"0"</span> <span class="synIdentifier"> role=</span><span class="synConstant">"button"</span> <span class="synIdentifier"> aria-haspopup=</span><span class="synConstant">"listbox"</span> <span class="synIdentifier"> aria-labelledby=</span><span class="synConstant">"demo-simple-select-filled"</span> <span class="synIdentifier"> </span><span class="synType">id</span><span class="synIdentifier">=</span><span class="synConstant">"demo-simple-select-filled"</span> <span class="synIdentifier"> ></span> 未着手 <span class="synIdentifier"></</span><span class="synStatement">div</span><span class="synIdentifier">></span> <span class="synComment"><!-- ここまで --></span> <span class="synIdentifier"><</span><span class="synStatement">input</span> <span class="synIdentifier"> aria-</span><span class="synType">hidden</span><span class="synIdentifier">=</span><span class="synConstant">"true"</span> <span class="synIdentifier"> </span><span class="synType">tabindex</span><span class="synIdentifier">=</span><span class="synConstant">"-1"</span> <span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"MuiSelect-nativeInput"</span> <span class="synIdentifier"> </span><span class="synType">value</span><span class="synIdentifier">=</span><span class="synConstant">"waiting"</span> <span class="synIdentifier"> /><</span>svg <span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"MuiSvgIcon-root MuiSelect-icon MuiSelect-iconOutlined"</span> <span class="synIdentifier"> focusable=</span><span class="synConstant">"false"</span> <span class="synIdentifier"> viewBox=</span><span class="synConstant">"0 0 24 24"</span> <span class="synIdentifier"> aria-</span><span class="synType">hidden</span><span class="synIdentifier">=</span><span class="synConstant">"true"</span> <span class="synIdentifier"> ></span> <span class="synIdentifier"><</span>path<span class="synIdentifier"> d=</span><span class="synConstant">"M7 10l5 5 5-5z"</span><span class="synIdentifier">></</span>path<span class="synIdentifier">></span> <span class="synIdentifier"></</span>svg<span class="synIdentifier">></span> <span class="synIdentifier"><</span><span class="synStatement">fieldset</span> <span class="synIdentifier"> aria-</span><span class="synType">hidden</span><span class="synIdentifier">=</span><span class="synConstant">"true"</span> <span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"PrivateNotchedOutline-root-29 MuiOutlinedInput-notchedOutline"</span> <span class="synIdentifier"> </span><span class="synType">style</span><span class="synIdentifier">=</span><span class="synConstant">"padding-left: 8px"</span> <span class="synIdentifier"> ></span> <span class="synIdentifier"><</span><span class="synStatement">legend</span><span class="synIdentifier"> </span><span class="synType">class</span><span class="synIdentifier">=</span><span class="synConstant">"PrivateNotchedOutline-legend-30"</span><span class="synIdentifier"> </span><span class="synType">style</span><span class="synIdentifier">=</span><span class="synConstant">"width: 0.01px"</span><span class="synIdentifier">></span> <span class="synIdentifier"><</span><span class="synStatement">span</span><span class="synIdentifier">></span><200b><span class="synIdentifier"></</span><span class="synStatement">span</span><span class="synIdentifier">></span> <span class="synIdentifier"></</span><span class="synStatement">legend</span><span class="synIdentifier">></span> <span class="synIdentifier"></</span><span class="synStatement">fieldset</span><span class="synIdentifier">></span> <span class="synIdentifier"></</span><span class="synStatement">div</span><span class="synIdentifier">></span> </pre> <pre class="code lang-javascript" data-lang="javascript" data-unlink><Select id=<span class="synConstant">"demo-simple-select-filled"</span> value=<span class="synIdentifier">{</span>task.<span class="synStatement">status</span><span class="synIdentifier">}</span> variant=<span class="synConstant">"outlined"</span> className=<span class="synIdentifier">{</span>classes.statusMenu<span class="synIdentifier">}</span> > <MenuItem value=<span class="synConstant">"waiting"</span>>未着手</MenuItem> <MenuItem value=<span class="synConstant">"working"</span>>作業中</MenuItem> <MenuItem value=<span class="synConstant">"completed"</span>>完了</MenuItem> <MenuItem value=<span class="synConstant">"pending"</span>>保留</MenuItem> </Select> </pre> <h3>方法</h3> <p><code>MenuItem</code>のinput部分の<code>MuiOutlinedInput-input</code>に対してスタイルを設定する</p> <pre class="code lang-css" data-lang="css" data-unlink>statusMenu: <span class="synIdentifier">{</span> <span class="synConstant">'& .MuiOutlinedInput-input'</span>: { paddingBottom: <span class="synConstant">'7px'</span><span class="synSpecial">,</span> paddingTop: <span class="synConstant">'7px'</span><span class="synSpecial">,</span> <span class="synIdentifier">}</span><span class="synSpecial">,</span> <span class="synError">}</span><span class="synSpecial">,</span> </pre>
JSのbind、及び`this`について理解を少し深める
2021/01/05 20:24
<h4>bindそのものについて</h4> <p>JSのbindの用法を知り、「どういう時に使われるのか」が漠然とイメージできるようになりたかったため、概要と使われ方を調べた。</p> <p>とりあえず以下のサイトのデモコードを自分なりにいじってどういう挙動なのかは調べた。</p> <p><a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Function/bind">Function.prototype.bind() - JavaScript | MDN</a></p> <pre class="code lang-javascript" data-lang="javascript" data-unlink><span class="synStatement">const</span> module = <span class="synIdentifier">{</span> a: 50, b: 30, text: <span class="synConstant">'this is test'</span>, showText: <span class="synIdentifier">function</span>()<span class="synIdentifier">{</span> <span class="synStatement">return</span> <span class="synIdentifier">this</span>.text; <span class="synIdentifier">}</span>, <span class="synIdentifier">}</span>; <span class="synStatement">const</span> moduleShow = module.showText; console.log(moduleShow); <span class="synComment">// moduleから抜き出した関数にmodule自体をbindする</span> <span class="synComment">// moduleShow内のthis = bindされたmoduleとなる</span> <span class="synComment">// そのため、this.text = module.text、になる</span> <span class="synStatement">const</span> boundGetX = moduleShow.bind(module); console.log(boundGetX()); </pre> <p><br></p> <p>その他、bindの概要、callとの違いについては下記の記事を見てイメージは出来た。 <a href="https://itsakura.com/js-bind">JavaScript thisの内容を指定する(bindメソッド) | ITSakura</a></p> <p>ただ、こいつがどういう目的で使われるかは分からなかった。<a href="#f-81413229" name="fn-81413229" title="こういったサンプルを見て、「じゃあこういうものにも応用できるな」と考えつく能力もプログラマに必要不可欠な能力だよな、と最近感じている">*1</a></p> <p>単純に、関数内のthis(thisがない場合はbind内の第一引数にnullを指定する)を特定のものに設定する(=undefinedにしない)場合にbindを使う、という使い方でいいのだろうか。</p> <h4>アロー関数内でのthisの扱われ方とbindの比較</h4> <p>ここまで調べて、そういえばJSの通常関数とアロー関数ではthisの指すものが異なる、という話しを思い出した。</p> <p><a href="https://qiita.com/mejileben/items/69e5facdb60781927929">【JavaScript】アロー関数式を学ぶついでにthisも復習する話 - Qiita</a></p> <p><a href="https://qiita.com/suin/items/a44825d253d023e31e4d">JavaScript: 通常の関数とアロー関数の違いは「書き方だけ」ではない。異なる性質が10個ほどある。 - Qiita</a></p> <p><br></p> <p>両者の<code>this</code>に関する違いとしては、アロー関数は<code>this</code>を束縛し、通常関数は<code>this</code>を束縛しない(=関数呼び出し元(レシーバ)をthisとする)という点である。</p> <p>下記のコードを例に比較する。</p> <ul> <li>通常関数</li> </ul> <pre class="code lang-javascript" data-lang="javascript" data-unlink> <span class="synIdentifier">this</span>.name = <span class="synConstant">"globalName"</span>; <span class="synComment">// 通常関数</span> <span class="synIdentifier">function</span> showName() <span class="synIdentifier">{</span> console.log(<span class="synIdentifier">this</span>.name); <span class="synIdentifier">}</span> <span class="synIdentifier">let</span> arrowFunc = <span class="synIdentifier">{</span> name: <span class="synConstant">"john"</span>, func: showName, <span class="synIdentifier">}</span>; arrowFunc.func(); => john <span class="synComment">// bindを使った場合</span> showName.bind(arrowFunc)(); => john </pre> <p><code>arrowFunc.func()</code>の返り値が<code>john</code>となっており、これはarrowFunc.nameの値であることが分かる。 このことから、<code>arrowFunc.func()</code>、つまりは<code>arrowFunc.showName()</code>のshowName内部のthisはarrowFunc(レシーバ)を指していたことが分かる。 <br></p> <ul> <li>アロー関数</li> </ul> <pre class="code lang-javascript" data-lang="javascript" data-unlink> <span class="synIdentifier">this</span>.name = <span class="synConstant">"globalName"</span>; <span class="synComment">// アロー関数</span> <span class="synStatement">const</span> showName = () => <span class="synIdentifier">{</span> console.log(<span class="synIdentifier">this</span>.name); <span class="synIdentifier">}</span>; <span class="synIdentifier">let</span> arrowFunc = <span class="synIdentifier">{</span> name: <span class="synConstant">"john"</span>, func: showName, <span class="synIdentifier">}</span>; arrowFunc.func(); => globalName </pre> <p><code>arrowFunc.func()</code>の返り値が「globalName」となっている。これは最初に定義した<code>this.name = "globalName"</code>のnameの値が表示されていることが分かる。 ここで、アロー関数内のthisについてのリファレンスを見てみる。</p> <blockquote><p>アロー関数自身は this を持ちません。レキシカルスコープの this 値を使います。つまり、アロー関数内の this 値は通常の変数検索ルールに従います。このためスコープに this 値がない場合、その一つ外側のスコープで this 値を探します。</p></blockquote> <p><a href="https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Functions/Arrow_functions#No_separate_this">アロー関数 - JavaScript | MDN</a></p> <p><br></p> <p>アロー関数である<code>showName</code>が定義された際、関数内のthisは更に外側のthisを見ていたことになる。 今回Node上で上記コードを実行したため、thisとして定義されていたのは<code>{name: "globalName"}</code>だったため、<code>showName</code>関数内のconsole.logで表示されたthis.nameは、コードの最初に定義したthis.nameだった、ということになる。</p> <p><br></p> <p>ちなみにトッ<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%EC%A5%D9">プレベ</a>ル、グロー<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D0%A5%EB%A5%B9">バルス</a>コープあたりはここを参考にした。</p> <p><a href="https://qiita.com/qeema/items/0b7e2ff4e33703a42a40">JavaScriptのトップレベルスコープは常にグローバルスコープではなかった - Qiita</a></p> <h4>まとめ</h4> <p>改めて<code>bind</code>、通常関数とアロー関数それぞれでのthisの使い方を確認した。 通常関数とアロー関数の違いについては他にも色々あるが、一旦知りたいと思っていたことを確認することができた。</p> <div class="footnote"> <p class="footnote"><a href="#fn-81413229" name="f-81413229" class="footnote-number">*1</a><span class="footnote-delimiter">:</span><span class="footnote-text">こういったサンプルを見て、「じゃあこういうものにも応用できるな」と考えつく能力も<a class="keyword" href="http://d.hatena.ne.jp/keyword/%A5%D7%A5%ED%A5%B0%A5%E9%A5%DE">プログラマ</a>に必要不可欠な能力だよな、と最近感じている</span></p> </div>
需要が薄いMaterial-UIのvalidationの一例
2021/01/04 12:54
<p>空文字を許容しない、というバリデーションを一部分だけ書きたい、しかしそのために本格的なバリデーションの機構を組むのはめんどくさくて死にそう、という時にその場しのぎで書いたもの。</p> <pre class="code lang-javascript" data-lang="javascript" data-unlink> <TextField label=<span class="synConstant">"名前"</span> variant=<span class="synConstant">"outlined"</span> margin=<span class="synConstant">"normal"</span> required <span class="synComment">// input.valueに入力された文字が入っているものとして、空文字の場合は input.value はfalseを返す</span> <span class="synComment">// 上記の場合に{ error: true }を返すことで <TextField error /> と書いた時と同じようになる</span> <span class="synComment">// { error: false } の場合はerrorは指定されていない状態になる</span> <span class="synIdentifier">{</span>...(!input.value ? <span class="synIdentifier">{</span> error: <span class="synConstant">true</span> <span class="synIdentifier">}</span> : <span class="synIdentifier">{</span> error: <span class="synConstant">false</span> <span class="synIdentifier">}</span>)<span class="synIdentifier">}</span> /> </pre>