Object.observe() doesn't work native Image object

165 views Asked by At

This doesn't work (in chrome 39 on OSX):

var x = new Image();
Object.observe(x, function(){console.log('i never run');})
x.src = 'http://www.foo.com';
console.log('has been set: ' + x.src);

But this will:

var x = new function nonNative(){};
Object.observe(x, function(){console.log('i will run');})
x.src = 'http://www.foo.com';

And so will this:

var x = new XMLHttpRequest();
Object.observe(x, function(){console.log('so will i');})
x.src = 'http://www.foo.com';

So the problem isn't related directly to Image being a native constructor (since XMLHttpRequest works as expected) - it seems to be something specific to setting img.src. I can only guess it's because setting an src behaves a lot like a method (in that it causes the request to be made). Is there such a thing in JS as a method which can be called like a property?

Assuming it's not that, does anyone know/can guess if this is desired behaviour of Object.observe (couldn't see anything in mdn docs), and if not, where might be the best place for me to report it as a bug?

2

There are 2 answers

2
AudioBubble On BEST ANSWER

x.src = is a sort of shorthand for x.setAttribute('src', ..., and setting attributes does not trigger Object.observe--this is the DOM world, not the JS object world. Attributes on HTMLElements are not JS object properties (although sometimes they pretend to be; actually they lurk within the attributes property as a NamedNodeMap), and JS object properties are what Object.observe observes. You can verify this by setting a non-attribute property on your image, and see the observer function firing.

Setting src on XMLHttpRequest works because XMLHttpRequest is just a plain old JS object and src is just a plain old property on it.

If you want to observe attribute changes, you can use mutation observers.

0
loganfsmyth On

As others have mentioned, src is not an attribute, it is a defined getter/setter pair, so by assigning it, you are actually calling a function.

Since this is a DOM element, you'd be better off using MutationObserver.

var x = new Image();
var observer = new MutationObserver(function(){
    console.log('i will run');
});

observer.observe(x, {attributes: true});

x.src = 'http://www.example.com.com'