I need to setup shorthands for several DOM accessor methods, namely - getElementsByClassName
( qCls
), getElementById
( qId
), querySelector
( q
), querySelectorAll
( Q
) - such that they are available:
q(selector)
as a shorthand for document.querySelector(selector)
throughout my code (in any scope or context). paragraph.q(selector)
as a shorthand for paragraph.querySelector(selector)
. I know the manual way to do this is:
window.Q = function(sel){ console.dir(document.querySelectorAll(sel)); }; Node.prototype.Q = function(sel){ console.dir(this.querySelectorAll(sel)); }; // TEST var p = document.querySelector("p"); Q("a"); // should have two elements pQ("a"); // should have one element
<a>1</a> <p><a>2</a></p>
But this has duplicacy - repeating exactly the same function again with only a minor difference ( document
vs this
) - so I intend to eliminate that duplicacy . 1
Now, what I think would work to achieve this is a pattern like:
window.Q = helperFunc(someFlag);
Node.prototype.Q = helperFunc(someOtherFlag);
where the helperFunc
handles the logic for the return value, based on the flags. Based on this, I wrote the following:
function outputQFunc(context) {
return function(selector) {
console.dir(context.querySelectorAll("a"));
};
}
window.Q = outputQFunc(document);
Node.prototype.Q = outputQFunc(this);
However, this has the obvious downside that the this
context for Node.prototype.Q
permanently points to the global scope, instead of the node which called this function. I could instead eliminate the context
:
function outputQFunc() {
return function(selector) {
console.dir(this.querySelectorAll("a"));
};
}
but then the this
does not point to the document
in case of the window.Q
.
So, my question is, how to achieve this?
Notes:
filter
s and stuff to the result of doc.qsAll
before return
ing it. In such cases, the duplicacy magnifies. Once my query got resolved, if anyone is interested in the final code I reached, this is it , which I personally find very DRY and extensible:
var DOM_HELPERS = {
/**
* short hand for document.querySelector
* @param {string} selector selector to match element
*/
q: function(selector) {
return this.querySelector(selector);
},
/**
* short hand for document.querySelectorAll
* @param {string} selector selector to match elements
*/
Q: function(selector) {
return this.querySelectorAll(selector);
},
/**
* short hand for document.getElementById
* @param {string} id selector to match element
*/
qId: function(id) {
return this.getElementById(id);
},
/**
* short hand for document.getElementsByClassName
* @param {string} cls selector to match elements
*/
qCls: function(cls) {
return this.getElementsByClassName(cls);
}
};
for (var i = 0, funcs = Object.keys(DOM_HELPERS), len = funcs.length, funcName, func; i < len; i++) {
funcName = funcs[i];
func = DOM_HELPERS[funcName];
window[funcName] = func.bind(document);
Node.prototype[funcName] = func;
}
Use bind
on your helper function to specify a custom this
context for window.Q
(and use the default this
otherwise, which will point to the proper calling context when called on a node):
function qSA(sel) { console.dir(this.querySelectorAll(sel)); } window.Q = qSA.bind(document); Node.prototype.Q = qSA; // TEST var p = document.querySelector("p"); Q("a"); // should have two elements pQ("a"); // should have one element
<a>1</a> <p><a>2</a></p>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.