Object.watch () สำหรับทุกเบราว์เซอร์?


118

โปรดทราบว่าObject.WatchและObject.Observeทั้งสองเลิกใช้งานแล้วในขณะนี้ (ณ มิ.ย. 2018)


ฉันกำลังมองหาวิธีง่ายๆในการตรวจสอบวัตถุหรือตัวแปรสำหรับการเปลี่ยนแปลงและพบ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()ใน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 คุณสามารถใช้ onPropertyChange ใน IE
scunliffe

1
แทนที่ document.write () ด้วย alert () มันควรจะทำงานได้ดี
Ionuț G. Stan

คำตอบ:


113

(ขออภัยสำหรับการโพสต์ข้าม แต่คำตอบที่ฉันให้กับคำถามที่คล้ายกันนี้ใช้ได้ดีที่นี่)

ฉันได้สร้างวัตถุขนาดเล็กนาฬิกาชิมสำหรับสิ่งนี้เมื่อไม่นานมานี้ ทำงานได้ใน IE8, Safari, Chrome, Firefox, Opera ฯลฯ


10
คำอธิบายเกี่ยวกับวิธีการใช้งานและวิธีการทำงานภายในจะดีสำหรับพวกเราที่ไม่ใช่ผู้เชี่ยวชาญ JS ขอบคุณ
maraujop


jsfiddle.net/kSWxPคำแนะนำ: ใช้ Firefox (คำสั่งหลังไม่ถูกพิมพ์ใน Chrome)
Mars Robertson


ฉันมีความคิดความรู้Object.defineProperty()ที่มีอยู่ ฉันลงเอยด้วยการดูข้อมูลอ้างอิงMDNเพื่อดูว่ามันทำงานอย่างไร
jumpnett

19

ปลั๊กอินนั้นใช้ตัวจับเวลา / ช่วงเวลาเพื่อตรวจสอบการเปลี่ยนแปลงของวัตถุซ้ำ ๆ อาจจะดีพอ แต่โดยส่วนตัวแล้วฉันต้องการความฉับไวมากกว่าในฐานะผู้สังเกตการณ์

นี่คือความพยายามที่จะนำwatch/ unwatchเพื่อ IE: 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);

ไม่หวานเท่า แต่ในฐานะผู้สังเกตการณ์คุณจะได้รับแจ้งทันที


ใช่ดูการประทับเวลาเหล่านั้น ... ไม่จำเป็นต้องลงคะแนน crescentfresh ยังเพิ่มข้อมูลเพิ่มเติมในโพสต์แม้ว่าจะเป็นลิงก์เดียวกันก็ตาม ในขณะเดียวกันฉันได้ลองใช้รหัสที่พบในหน้านั้นแล้วและยังพบปัญหา ฉันอาจจะมองข้ามบางสิ่งไป ฉันได้อัปเดตโพสต์ต้นฉบับของฉันพร้อมข้อมูลเพิ่มเติม ...
SeanW

13

คำตอบสำหรับคำถามนี้ค่อนข้างล้าสมัย Object.watchและObject.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

คุณจะได้ใช้Object.observe () จาก ES7 นี่คือโพลีฟิลล์ แต่Object.observe () ถูกยกเลิกแล้ว ขอโทษคน!


ฉันไม่สามารถทำให้ polyfill นี้ทำงานใน ios safari ได้ ฉันได้รับข้อผิดพลาด: undefined ไม่ใช่ฟังก์ชัน (การประเมิน 'Object.observe (a.imgTouch, function (a) {console.debug ("lastX:" + a)})')
infomofo

@infomofo สวัสดีคุณต้องการเปิดปัญหาในหน้าโครงการพร้อมรายละเอียดทั้งหมดที่คุณสามารถให้ได้หรือไม่? ฉันยังไม่ได้ทดสอบบน iOS แต่จะตรวจสอบปัญหา
MaxArt

6

โปรดทราบว่าใน Chrome 36 ขึ้นไปคุณสามารถใช้ได้Object.observeเช่นกัน นี้เป็นจริงส่วนหนึ่งของมาตรฐาน ECMAScript อนาคตและไม่ใช่คุณสมบัติที่เบราว์เซอร์ที่เฉพาะเจาะจงเช่นของ Object.watchMozilla

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

เรียบง่ายและ
สง่างาม

1

ฉันใช้Watch.jsในโครงการหนึ่งของฉัน และใช้งานได้ดีหนึ่งในข้อได้เปรียบหลักของการใช้ไลบรารีนี้คือ:

"ด้วย 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>

ง่ายๆแค่นี้เอง!


-2

ฉันยังคิดว่าตอนนี้ทางออกที่ดีที่สุดคือการใช้ Watch.JS ค้นหาบทช่วยสอนที่ดีที่นี่: ฟัง / ดูการเปลี่ยนแปลงวัตถุหรืออาร์เรย์ใน Javascript (เหตุการณ์เปลี่ยนแปลงคุณสมบัติบนวัตถุ Javascript)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.