'document.getElementById().value - override or know when is accessed

Without explaining the details of the project I'm working on in too much detail, I am trying to determine a way in which I can either implement an event listener for when document.getElementById().value is accessed, or override it in a similar way to an object, and define custom behaviour for the getting and setting of this value. Is this possible?

I've tried the following, to no avail:

Object.defineProperty(document.getElementById, 'nodeValue', {
    get: function () {
        console.log('document.getElementById value accessed');
        return this.nodeValue;
    },
    set: function (value) {
        console.log('document.getElementById value set');
        this.nodeValue = value;
    }
});

and the same as above but with value instead of nodeValue:

Object.defineProperty(document.getElementById, 'value', {
    get: function () {
        console.log('document.getElementById value accessed');
        return this.value;
    },
    set: function (value) {
        console.log('document.getElementById value set');
        this.value = value;
    }
});

Apologies if this seems a somewhat farfetched approach, the intricacies of JavaScript behind-the-scenes isn't something I am too familiar with. The above code does show what I am trying to achieve, however. I just don't know how!

I've spent some time on MDN trying to understand just how this works and from what I can gather, getElementById() returns an Element which inherits from the Node interface which contains a nodeValue, and I this that this nodeValue is what I am interested in, but I cannot be certain.

Edit: I'm looking for this behaviour to be generic, I have more than one (but an unknown number of) elements, so I'm not trying to apply this to a specific element.



Solution 1:[1]

First, modifying Element object is a bad idea. Extending it, is bad, but not as bad as modifying it. This is because, JavaScript implementation on web browser does not put details on how the underlying API works. For example,

1. Modify Element Object

We have a document as follows:

<div>
  <h1 id="elem-id">Header Content</h1>
</div>

we could get its id by calling these instructions

let elem = document.getElementById('elem-id');
elem.getAttribute('id'); // 'elem-id';

We can modify getAttribute() by using:

Element.prototype.getAttribute = function (attributeKey) {
// Implement your own function here
return 'ok';
}

Next, when you call elem.getAttribute('id') it should return ok.

This is bad because there is no way to revert back to default implementation.

2. Extending Element Object

Next less bad stuff is, extending Object. We could simply do:

Element.prototype.getAttributeAndFireEvent = function (attributeKey) {
  console.log(`getting attribute for ${attributeKey}`); // Could be an eventEmitter
  return this.getAttribute(attributeKey);
}

then, we could use these methods by calling it like:

elem.getAttributeAndFireEvent('elem-id');

This will work but please be careful in modifying global object, it may cause unintended effect.

References:

  1. In Javascript, can you extend the DOM?

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Raynal Gobel