4

As we know we can assign a function/method to another variable and execute it anytime with the assigned variable.

const logger = {
  log: (text) => {
    console.log(text);
  },
};

const log = logger.log;
logger.log("Log test");
log("Log test 2");

But why we can't assign document.querySelector to a variable and use it. querySelector is also a method of the document object.

    console.log( typeof document.querySelector ) // function

const myDocument = document.querySelector;
myDocument("body");  // Uncaught TypeError: Illegal invocation
DecPK
  • 24,537
  • 6
  • 26
  • 42

2 Answers2

7

querySelector requires that it is bound to the instance of the document class. It checks for this internally. When assigning to a variable outside the scope of its owning class, it’s unable to perform the necessary logic of querying against the document instance to which it should belong.

This can be forced, by binding the method to the document instance:

const querySelector = document.querySelector.bind(document)

The above will bind references to this from within the querySelector method to reference the document instance on subsequent calls, regardless of the fact it is at this point a standalone function in the global scope.

You can see a similar loss of ‘this’ scope in your logger class with the following:

const logger = {
  log: function() {
    console.log(this.toString());
  },
};

const log = logger.log;
logger.log(); // [object Object] (the logger object)
log(); // [object Window] (the global object)
mindfullsilence
  • 344
  • 9
  • 23
2

Try in this way:

const myDocument = document.querySelector.bind(document);
myDocument("body");
dellink
  • 544
  • 3
  • 16
  • yup, it worked but what is the reason behind this. Why we can't invoke it without binding with the `document` object – DecPK Feb 26 '21 at 07:40
  • I didn't bind the `log` method of the `logger` object. But it worked – DecPK Feb 26 '21 at 07:47