First we have to understand what bind
makes. According to documentation:
creates a new Function that, when called, has its this keyword set to the provided value
That is, the bind
creates a new function which, when called, has the this
set to the value you were informed. So when you do:
let _ = document.querySelector.bind(document);
let __ = document.querySelectorAll.bind(document);
Are you saying that _
will always call document.querySelector
, and __
will always call document.querySelectorAll
.
That’s why _('alguma coisa')
works because it’s like you call document.querySelector('alguma coisa')
. But the return of this function is a HTMLElement
, who does not have the method __
(remember that __
was defined as a function calling document.querySelectorAll
).
A solution to do what you want would be to define __
in the prototype of HTMLElement
, making it point to the desired method (in case, querySelectorAll
):
let _ = document.querySelector.bind(document);
HTMLElement.prototype.__ = HTMLElement.prototype.querySelectorAll;
_('#abc').__('span').forEach(s => console.log(s.innerText));
<p id="abc">
Lorem <span>ipsum</span> dolor <span>sit</span> amet.
</p>
Thus, _
keeps calling document.querySelector
, but __
calls the querySelectorAll
of HTMLElement
returned by _
.
Of course you can keep both options (both on document
how much in the prototype):
let _ = document.querySelector.bind(document);
let __ = document.querySelectorAll.bind(document);
HTMLElement.prototype._ = HTMLElement.prototype.querySelector;
HTMLElement.prototype.__ = HTMLElement.prototype.querySelectorAll;
__('span').forEach(s => console.log(s._('a').innerText));
_('#abc').__('span').forEach(s => console.log(s.innerText));
<p id="abc">
Lorem <span>ipsum <a href="">link1</a></span> dolor <span>sit <a href="">link2</a></span> amet.
</p>
So when _
or __
are called directly, will be calling the methods of document
, and when they are called in the result of these, they will be calling the methods of the respective HTMLElement
's.