Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is happening in the console when I look at getter properties on DOM objects?

When running the following code in the console:

console.dir(document);

In Chrome, I see, among other things:

enter image description here

This seems to imply that the domain property is directly on the document object. However, it isn't.

console.log(document.hasOwnProperty('domain'));

In Chrome 72, going up the prototype chain, it appears to be on Document.prototype:

console.log(Document.prototype.hasOwnProperty('domain'));
console.log(Object.getOwnPropertyDescriptor(Document.prototype, 'domain'));

(In FF 56 and perhaps some other browsers, it appears to be on HTMLDocument.prototype instead)

As you can see from the snippet, the property is actually composed of a getter and a setter. But, I was under the impression that getters are shown in the console as (...), like in this image, which you had to click on the (...) to invoke the getter.

If I create a similar object, one whose prototype contains a getter/setter property, and I log the object, the getter does not get invoked while examining it:

// look at results in Chrome's browser console, not snippet console
class theProto {
  get foo() {
    return 'fooVal';
  }
  set foo(arg) {
    // do something
  }
}
class theClass extends theProto {
}
const instance = new theClass();
console.dir(instance);

enter image description here

The same sort of behavior can be seen for many properties on document. For example, all of the other properties you can see in the first screenshot also appear to be getters/setters on one of the prototype objects, and none of them are on document itself:

console.log(
  ['dir', 'doctype', 'documentElement', 'documentURI', 'embeds', 'fgColor', 'firstChild', 'firstElementChild']
  .some(prop => document.hasOwnProperty(prop))
);

You can also see this on window properties, as well as elements. This happens in FF as well.

const input = document.createElement('input');
// console.dir(input);

// but the own property list is empty!
console.log(Object.getOwnPropertyNames(input));
<img src="https://i.stack.imgur.com/R5u3S.png">

Is it possible to create an object with the same logging behavior as these, where console.diring an object will also invoke any getters in the prototype chain immediately, instead of displaying (...)? How would I modify my theClass snippet? Or, do certain predefined objects (like DOM objects) just have an exception to the normal logging behavior?

I know how to invoke the getters programmatically, I'm just curious about the seeming inconsistency.

like image 404
Snow Avatar asked Feb 20 '19 10:02

Snow


1 Answers

Is it possible to create an object with the same logging behavior as these, where console.diring an object will also invoke any getters in the prototype chain immediately, instead of displaying (...)?

Thecnically, yes, despite it will not exactly evaluate the getters (I'm not sure whether the values you see are evaluated when you console.dir them). You need to evaluate the property. However, using hasOwnProperty will return true.

// look at results in Chrome's browser console, not snippet console
class theProto {
  get foo() {
    return 'fooVal';
  }
  set foo(arg) {
    // do something
  }
}
class theClass extends theProto {
   foo = (() => theProto.prototype.foo)(); // or, really, just (() => this.foo)();
}
const instance = new theClass();
console.dir(instance);

enter image description here

Working fiddle: https://jsfiddle.net/vL6smo51/1/

like image 85
briosheje Avatar answered Nov 19 '22 06:11

briosheje