{{ fullName }}
``` ## 算出プロパティの特徴 「算出プロパティの代わりに、同じような関数をメソッドとして定義することも可能です。 最終的には、2つのアプローチは完全に同じ結果になります。 しかしながら、算出プロパティは依存関係にもとづきキャッシュされるという違いがあります。 算出プロパティは、それが依存するものが更新されたときにだけ再評価されます。」 算出プロパティ のドキュメントからの引用 ## 算出プロパティの特徴 依存しているプロパティが変更されない限り、一度計算した値(キャッシュ)を返す。依存しているプロパティが変更された場合、再計算をおこなう。 ## 算出プロパティに対する疑問 * 「依存しているプロパティが変更されない限り」→ 依存しているプロパティをどのように把握しているか * 「依存しているプロパティが変更された場合」→ 変更の検知とキャッシュの破棄をどのようにおこなっているか ## 依存関係をどのように追跡するか ```javascript { fullName: function () { return this.firstName + ' ' + this.lastName; } } ``` → 算出プロパティ は firstName, lastName 各プロパティに依存している ## 再計算をどのようにおこなっているか ```javascript vm.fullName // John Smith vm.firstName = 'Bob'; vm.fullName // Bob Smith ``` → 変更があったら再計算をおこなう ## 実装を理解するための内部のオブジェクト - リアクティブプロパティ - Watcher インスタンス(算出プロパティ) ## リアクティブプロパティ ## リアクティブプロパティ * Object.defineProperty で getter/setter を定義し、参照・代入にフック処理が入ったプロパティ。Vue.js 内部でこのように呼ばれています * getter で依存関係の追跡, setter で状態の変更の通知 * 将来的に Object.defineProperty ではなく ES2015 Proxy を使う実装になる予定( refs: [Staet of Vue Jan '17 at This.JavaScript with Evan You, Vue Core Team](https://www.youtube.com/watch?v=E84m5KrzOZk) ) * src/core/observer/index.js の defineReactive 関数 src/core/observer/index.js の defineReactive 関数 ```javascript // key example: firstName, lastName Object.defineProperty(obj, key, { enumerable: true, configurable: true, get: function reactiveGetter () { // 依存関係の追跡 }, set: function reactiveSetter (newVal) { // 状態の変更の通知 } }) ``` ## Watcher インスタンス(算出プロパティ) ## Watcher インスタンス(算出プロパティ) * 算出プロパティ ≒ Watcher インスタンス (以後の説明で、Watcher インスタンス は 算出プロパティ だと思ってください) * 計算の内容 (getter プロパティ) * 計算をおこなう必要があるか (dirty プロパティ) * 計算の結果 (value プロパティ) * src/core/observer/watcher.js src/core/instance/state.js の makeComputedGetter 関数 ```javascript function makeComputedGetter (getter, owner) { const watcher = new Watcher(owner, getter, noop, { lazy: true }) return function computedGetter () { if (watcher.dirty) { watcher.evaluate() } if (Dep.target) { watcher.depend() } return watcher.value } } ``` ### リアクティブプロパティ と Watcher インスタンス(算出プロパティ)の関係 以下のそれぞれのフェーズで関係を追う * 依存関係の追跡 * 状態の変更の通知 と 再計算 ## 依存関係の追跡 初回のレンダリング・計算を行う前の段階では Watcher インスタンス と リアクティブプロパティ に関係はない