tweeeetyのぶろぐ的めも

アウトプットが少なかったダメな自分をアウトプット<br>\(^o^)/

Object.observeとはなんなのか - データバインディングに使えそうなdefinePropertyからのgetNotifierでnotifyしてみたり

はじめに

Object.observeが気になったので自分なりに理解がてらまとめてみたメモ。
内容は浅めでなんなのか理解できる程度です。

おしな

  1. Object.observeとは
  2. Object.observeをシンプルに試す
  3. Object.observeのchangesとはなにか
  4. callbackが呼ばれるタイミングとchanges配列に追加されるタイミング
  5. changesをfilterしてみる
  6. Notifyでchange.typeを自分で指定してみる

1. Object.observeとは

いくつかの記事を引用させてもらいつつ自分なりに文章にしてみました。
記事タイトルからするとこれ説明してたら終わってしまいそうですねw

Object.observe() は任意のオブジェクトをObserve(監視)し、
何が変更、削除、または設定変更されたかのレポートを手軽に受け取ることができるAPI
Chrome 36 Beta以降で利用できる。 ほかのブラウザで使いたい場合も、PolymerのObserve-JSがObject.observeのpolyfillになっているので有用。

2. Object.observeをシンプルに試す

論よりコードということで、結局はどんなことができるのかを見てみます。

ソース
結果
解説

Object.observeですが、引数はこんな感じです。

第1引数...observe(監視)するオブジェクト
第2引数...オブジェクトに変更があった場合に受け取れるコールバック関数

21行目でmodel.title = 'chaaaaaaaaaange!';とすることで
modelのプロパティのtitleが変更され、
コールバックとして定義したobserverが呼ばれています。

changesについては後述しますが、ここではとりあえず以下のことがわかります

  • change.name変更があったpropertyの名前を受け取れる
  • change.type変更の種類を受け取れる
  • change.object[change.name]変更後の値を受け取れる
  • changeにはいろいろな情報が入ってる(変更前の値とか)
プチまとめ

Object.observe()にmodel(オブジェクト)を渡すことでオブジェクトを監視し、
変更があった際にobserve(コールバック)にchanges(変更内容)を渡して実行してくれる。
って感じですかね。

3. Object.observeのchangesとはなにか

今度はchangesについて見てみます。
上記の例でいうと、modelについてどんな変更をすると、change.typeにどんな値が入ってくるかを見てみます。

こちらもまずはソースと結果から

ソース
結果
解説

今回は主に下記のことを行ってみました。

  • modelに新しいプロパティを追加してみる
  • model.titleを変更してみる
  • definePropertiesでプロパティ設定を変更してみる
  • model.titleを削除してみる

8行目に入れたログconsole.log('changes length: ' + changes.length);でわかる通り、 changesは変更情報の配列になっています。

また、36行目のmodel = null;に対しては何も出力されません。

プチまとめ

Object.observeで監視したオブジェクトに対する変更情報は、
コールバックに渡されるchanges配列にまとめて格納される。

まとめるまでもないですが、変更内容とchange.typeはこんな感じです

change.type オブジェクトに行う変更
add プロパティを追加した
update プロパティを変更した
reconfigure プロパティの設定を変更した
delete プロパティを削除した

4. callbackが呼ばれるタイミングとchanges配列に追加されるタイミング

Object.observeでの監視、コールバック、changesなんかには簡単に理解できました。
コールバックはいつ呼ばれて、changesにはいつ情報が入るのでしょうか。
その辺を見てみたいと思います。

ソース
結果
解説

今度はmodel.titleへの変更のみを行ってみました。
また、変更する前にそれぞれconsole.logでログを出してます。

結果の通りですが、`change 1〜6"のconsole.logが呼ばれた後に
コールバックが呼ばれてます。変更情報をスタックしておいて処理が終わったらコールバックが呼ばれるようです。

また、change1〜4は同じ文字列を入れてますが、
変更内容が同一の場合は、changesに変更情報としてスタックされないようです。

プチまとめ

コールバックとchangesのタイミングについてまとめるとこんな感じですかね。

  • callbackは処理が終わった後に呼ばれ、changesには変更情報がスタックされている
  • changesにスタックされる変更情報は、プロパティの内容に変更があったとき

5. changesをfilterしてみる

コールバックのchangesを通して通知された変更にアクセスでき、
change.typeで変更の種類を知る事ができましたが、実は受け取る変更通知はfilterできます。

Object.observeの3番目の引数を指定することで可能となります。

ソース
結果
解説

処理としては変更・追加・削除を順番に行っていますが、
Object.observeの第3引数にchange.typeに対する値を配列で渡すことで、
受け取る通知をfilterできています。

今回は'delete'を指定しているので、'delete'に関する通知のみ出力されています。

プチまとめ

Object.observe(obj, callback, opt_acceptList)とすることで、
opt_acceptListとして渡したchange.typeのみ通知を受け取ることができる。

6. Notifyでchange.typeを自分で指定してみる

今までは特定のchange.typeにのみついて書いていましたが、
もちろんカスタム通知もできます。ということで早速。

ソース
結果
解説

Object.definePropertyを使ってmodelにhogeプロパティと、hogeに対するsetter、getterを定義しています。

また、setter、getterの中ではカスタム通知を発火(と呼ぶと何かしっくりきませんが)を呼ぶことで自前で定義したchange.typeを受け取ることができました!

注意としては、最初うまくいかず試行錯誤したんですが、
第3引数で['add', 'update', 'tekitou', 'fugafuga', 'aiueo']のようにaccept(許可)のlist渡さないとnotifyされませんでした。

プチまとめ

Object.definePropertyとObject.getNotifier(.notify)を使うことで独自のnotifyを作れる。
また、Object.observeの第3引数で指定しないと呼ばれない。

参考

今回の記事はこちらを参考にさせて頂いてます!thx!

まとめ

Object.observe実践ではまだ使えてませんが、使った感じシンプルですごくわかりやすいですね。
今までオブザーバーパターンのようなものを素のjsで書くのは大変だったので、Object.observeを用いることで格段に簡単になりそうです! enjoy!