1

I need to execute a js script when the hash of the page changes, I know there are many ways to know when the hash changes like using jQuery

$(window).on('hashchange', function() {
   // do something
});

I tried to use the Object.observe but it didn't work, I just whant to know why it didn't, why the callback doesn't fire after updating the document.location object.

Object.observe(document.location, function(changes) { 
    console.log(changes);
});
Khalid
  • 4,392
  • 5
  • 23
  • 50

2 Answers2

2

document.location along with many other DOM objects fall into the category of host objects which per spec do not have to behave like regular native JS objects. While Object.observe may work for some of these objects, it does not behave reliably and happens not to work for document.location.

Another example where it does not work is:

var el = document.createElement('div');
document.body.appendChild(el);
Object.observe(el, function(change) { console.log('changed ', change[0].name); })

el.id = "hello";
el.foo = "bar";
Jasvir
  • 476
  • 2
  • 4
  • that makes sens. on your example, it works for the attribute `foo` but not `id` , I tried on `document.location` , it worked for a random attribute but not on `.hash`. thanks for your answer – Khalid Mar 31 '15 at 14:55
0

I believe the reasons you are not able to observe document.location using Object.observe() is because document.location returns an object of type Location Object (which is special read-only interface) and not "Standard" Object.

From Mozilla docs:

The Document.location read-only property returns a Location object. The location property of the Document object refers to the Location object. Window.location is a read-only Location object.

Location interface: https://developer.mozilla.org/en-US/docs/Web/API/Location

Example:

console.log(document.location.__proto__); // returns Location {}
console.log(window.location.__proto__);   // returns Location {}
window.location === document.location // always true

The Object.observe() method is used for observing the changes to an object.

Example:

var o = { name: ''};
Object.observe(o, function(changes){
    changes.forEach(function(change) {
    console.log(change.type, change.name, change.oldValue);
});
});
o.name = 'foo'; // name is being observed

Look at the difference in their __proto__

console.log(document.location.__proto__); // returns Location {}
console.log(window.location.__proto__);   // returns Location {}
console.log(o.__proto__);                 // returns Object {}

Interesting enough if you test whether an object has in its prototype chain the prototype property of a constructor you can get:

console.log(document.location instanceof Object); // true
console.log(o instanceof Object); // true

Code sample:

var o = {
  name: ''
};
Object.observe(o, function(changes) {
  changes.forEach(function(change) {
    console.log(change.type, change.name, change.oldValue);
  });
});

o.name = 'foo';


console.log(document.location.__proto__); // returns Location {}
console.log(window.location.__proto__); // returns Location {}
console.log(o.__proto__); // returns Object {}


console.log(document.location instanceof Object); // true
console.log(o instanceof Object); // true
GibboK
  • 64,078
  • 128
  • 380
  • 620
  • would you please read my post again ? I know I can't do it on `document.location.hash` , I did it on `document.location`. It doesn't return an error, but it doesn't work – Khalid Mar 31 '15 at 14:18
  • I don't think that's right - the original question is observing document.location rather than document.location.hash. – Jasvir Mar 31 '15 at 14:18
  • 1
    Thanks guys, I will double check, and I will edit my answer thanks for your comments .... – GibboK Mar 31 '15 at 14:24