すべてのブラウザーのObject.watch()?


118

Object.WatchとのObject.Observe両方が現在非推奨になっていることに注意してください(2018年6月現在)。


オブジェクトまたは変数の変更を監視する簡単な方法を探していたところObject.watch()、MozillaブラウザーではサポートされているがIEではサポートされていないことがわかりました。だから私は誰かが何らかの同等のものを書いたかどうかを探して周りを探し始めました。

私が見つけた唯一のことはjQueryプラグインですが、それが最善の方法かどうかはわかりません。私は確かにほとんどのプロジェクトでjQueryを使用しているので、jQueryの側面については心配していません...

とにかく、質問:そのjQueryプラグインの実際の例を誰かに見せてもらえますか?うまく動かないのですが…

または、クロスブラウザで動作するより良い代替案を誰かが知っていますか?

回答後に更新

回答ありがとうございます!ここに投稿されたコードを試してみました:http : //webreflection.blogspot.com/2009/01/internet-explorer-object-watch.html

しかし、IEで動作させることができなかったようです。以下のコードはFirefoxでは正常に動作しますが、IEでは何も実行しません。Firefoxでは、watcher.status変更されるたびにdocument.write()in watcher.watch()が呼び出され、ページに出力が表示されます。IEではそれは起こりませんがwatcher.status、最後のdocument.write()呼び出しで正しい値が表示されるため(IEとFFの両方で)、値が更新されていることがわかります。しかし、コールバック関数が呼び出されない場合、それは一種の無意味です... :)

何か不足していますか?

var options = {'status': 'no status'},
watcher = createWatcher(options);

watcher.watch("status", function(prop, oldValue, newValue) {
  document.write("old: " + oldValue + ", new: " + newValue + "<br>");
  return newValue;
});

watcher.status = 'asdf';
watcher.status = '1234';

document.write(watcher.status + "<br>");

2
IIRCはIEでonPropertyChangeを使用できます
scunliffe

1
document.write()をalert()に置き換えます。正常に動作するはずです。
Ionuț G. Stan

回答:


113

(クロス投稿して申し訳ありませんが、私が同様の質問に与えたこの答えはここではうまくいきます)

このための小さなobject.watch shimを少し前に作成しました。IE8、Safari、Chrome、Firefox、Operaなどで動作します。


10
それを使用する方法とこれが内部でどのように機能するかについての説明は、JSマスターではない私たちにうれしいです。
maraujop


jsfiddle.net/kSWxPヒント:Firefoxを使用します(後者のステートメントはChromeでは印刷されません)
Mars Robertson


私はアイデアがObject.defineProperty()存在することを知っていました。最終的にMDNリファレンスを調べて、それがどのように機能するかを確認しました。
jumpnett 2015年

19

そのプラグインは、タイマー/間隔を使用して、オブジェクトの変更を繰り返し確認するだけです。多分十分ですが、個人的にはオブザーバーとしての即時性を求めています。

IEにwatch/ unwatchを導入する試みは次のとおりです:http : //webreflection.blogspot.com/2009/01/internet-explorer-object-watch.html

オブザーバーを追加するFirefoxの方法から構文を変更します。の代わりに :

var obj = {foo:'bar'};
obj.watch('foo', fooChanged);

あなたがやる:

var obj = {foo:'bar'};
var watcher = createWatcher(obj);
watcher.watch('foo', fooChanged);

それほど甘いわけではありませんが、オブザーバーとしてすぐに通知されます。


ええ、それらのタイムスタンプを見てください...投票する必要はありません。また、同じリンクであったとしても、クレセントフレッシュは投稿により多くの情報を追加しました。その間、そのページにあるコードを試してみましたが、まだ問題が発生しています。私は何かを見落としているかもしれません。元の投稿を詳細情報で更新しました...
SeanW

13

この質問に対する答えは少し時代遅れです。Object.watchObject.observeはどちらも非推奨であり、使用しないでください。

現在、Proxyオブジェクトを使用して、オブジェクトに加えられた変更を監視(およびインターセプト)できます。基本的な例は次のとおりです。

var targetObj = {};
var targetProxy = new Proxy(targetObj, {
  set: function (target, key, value) {
      console.log(`${key} set to ${value}`);
      target[key] = value;
  }
});

targetProxy.hello_world = "test"; // console: 'hello_world set to test'

ネストされたオブジェクトに加えられた変更を監視する必要がある場合は、専用のライブラリを使用する必要があります。Observable Slimを公​​開したところ、次のように機能しました。

var test = {testing:{}};
var p = ObservableSlim.create(test, true, function(changes) {
    console.log(JSON.stringify(changes));
});

p.testing.blah = 42; // console:  [{"type":"add","target":{"blah":42},"property":"blah","newValue":42,"currentPath":"testing.blah",jsonPointer:"/testing/blah","proxy":{"blah":42}}]

12

現在の回答

ターゲットへの変更を監視できる新しいProxyオブジェクトを使用します。

let validator = {
    set: function(obj, prop, value) {
        if (prop === 'age') {
            if (!Number.isInteger(value)) {
                throw new TypeError('The age is not an integer');
            }
            if (value > 200) {
                throw new RangeError('The age seems invalid');
            }
        }

        // The default behavior to store the value
        obj[prop] = value;

        // Indicate success
        return true;
    }
};

let person = new Proxy({}, validator);

person.age = 100;
console.log(person.age); // 100
person.age = 'young'; // Throws an exception
person.age = 300; // Throws an exception

2015年からの古い回答

ES7のObject.observe()を使用することもできます。これがポリフィルです。しかし、Object.observe()はキャンセルされました。ごめんなさい!


うーん、このポリフィルをiOSのサファリで機能させることができませんでした。エラーが表示されます:undefined is a function(evaluating 'Object.observe(a.imgTouch、function(a){console.debug( "lastX:" + a)})')
infomofo

@infomofoこんにちは、プロジェクトのページで問題を開きますか?iOSではテストしていませんが、問題を調査します。
MaxArt、2015年

6

Chrome 36以降でも使用できますObject.observe。これは実際には将来のECMAScript標準の一部であり、Mozillaのようなブラウザ固有の機能ではありませんObject.watch

Object.observeオブジェクトのプロパティでのみ機能しますが、Object.watch実稼働での使用ではなく、デバッグ目的で使用する場合よりもはるかに優れています。

var options = {};

Object.observe(options, function(changes) {
    console.log(changes);
});

options.foo = 'bar';

1
2018年と同様、これは非推奨であり、すべての主要なブラウザーでサポートされなくなりました
Sergei Panfilov

4

Object.definePropertyを使用できます。

でプロパティbarを見るfoo

Object.defineProperty(foo, "bar", {
  get: function (val){
      //some code to watch the getter function
  },

  set: function (val) {
      //some code to watch the setter function
  }
})

これは素晴らしい!しかし、私はそれを少し修正します:)元のセッターを上書きしないようにします。私は参照foo._someObject = foo.someObject
calmbird '22

シンプルかつelegent
ßãlãjî

1

私は私のプロジェクトの1つでWatch.jsを使用しました。このライブラリを使用する主な利点の1つは次のとおりです。

「Watch.JSを使用すると、開発方法を変更する必要はありません。」

例を以下に示します

//defining our object however we like
var ex1 = {
	attr1: "initial value of attr1",
	attr2: "initial value of attr2"
};

//defining a 'watcher' for an attribute
watch(ex1, "attr1", function(){
	alert("attr1 changed!");
});

//when changing the attribute its watcher will be invoked
ex1.attr1 = "other value";
<script src="https://cdn.jsdelivr.net/npm/melanke-watchjs@1.5.0/src/watch.min.js"></script>

これはこれと同じくらい簡単です!


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.