Making a short alias for document.querySelectorAll

孤街浪徒 提交于 2019-12-17 23:29:28

问题


I'm going to be running document.querySelectorAll() a whole lot, and would like a shorthand alias for it.

var queryAll = document.querySelectorAll

queryAll('body')
TypeError: Illegal invocation

Doesn't work. Whereas:

document.querySelectorAll('body')

Still does. How can I make the alias work?


回答1:


This seems to work:

var queryAll = document.querySelectorAll.bind(document);

bind returns a reference to the querySelectorAll function, changing the context of 'this' inside the querySelectorAll method to be the document object.

The bind function is only supported in IE9+ (and all the other browsers) - https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind


Update: In fact you could create shortcuts to a whole range of document methods like this:

var query = document.querySelector.bind(document);
var queryAll = document.querySelectorAll.bind(document);
var fromId = document.getElementById.bind(document);
var fromClass = document.getElementsByClassName.bind(document);
var fromTag = document.getElementsByTagName.bind(document);



回答2:


The JavaScript interpreter throws an error because querySelectorAll() should be invoked in document context.

The same error is thrown when you are trying to call console.log() aliased.

So you need to wrap it like this:

 function x(selector) {
     return document.querySelectorAll(selector);
 }



回答3:


A common answer is to use $ and $$ for querySelector and querySelectorAll. This alias mimics jQuery's one.

Example:

$ = document.querySelector.bind(document)
$$ = document.querySelectorAll.bind(document)

$('div').style.color = 'blue'
$$('div').forEach(div => div.style.background = 'orange')
div {
  margin: 2px;
}
<div>
  test
</div>
<section>
  <div>
    hello
  </div>
  <div>
    foo
  </div>
</section>



回答4:


My solution covers the four following use cases:

  • document.querySelector(...)
  • document.querySelectorAll(...)
  • element.querySelector(...)
  • element.querySelectorAll(...)

The code:

let doc=document,
    qsa=(s,o=doc)=>o.querySelectorAll(s),
    qs=(s,o=doc)=>o.querySelector(s);

In terms of parameters, the selector s is required, but the container element object o is optional.

Usage:

  • qs("div"): Queries the whole document for the first div, returns that element
  • qsa("div"): Queries the whole document for all divs, returns a nodeList of all those elements
  • qs("div", myContainer): Queries just within the myContainer element for the first div, returns that element
  • qsa("div", myContainer): Queries just within the myContainer element for all divs, returns a nodeList of all those elements

To make the code slightly shorter (but not quite as efficient), the qs code could be written as follows:

let qs=(s,o=doc)=>qsa(s,o)[0];

The code above uses ES6 features (let, arrow functions and default parameter values). An ES5 equivalent is:

var doc=document,
    qsa=function(s,o){return(o||doc).querySelectorAll(s);},
    qs=function(s,o){return(o||doc).querySelector(s);};

or the equivalent shorter but less efficient ES5 version of qs:

var qs=function(s,o){return qsa(s,o)[0];};

Below is a working demo. To ensure it works on all browsers, it uses the ES5 version, but if you're going to use this idea, remember that the ES6 version is shorter:

var doc = document;

var qs=function(s,o){return(o||doc).querySelector(s);},
    qsa=function(s,o){return(o||doc).querySelectorAll(s);}

var show=function(s){doc.body.appendChild(doc.createElement("p")).innerHTML=s;}

//           ____demo____       _____long equivalent______      __check return___      _expect__ 
//          |            |     |                          |    |                 |    |         |

let one   = qs("div");      /* doc.querySelector   ("#one") */ show(one  .id    ); // "one"
let oneN  = qs("div",one);  /* one.querySelector   ("div")  */ show(oneN .id    ); // "oneNested"
let many  = qsa("div");     /* doc.querySelectorAll("div")  */ show(many .length); // 3
let manyN = qsa("div",one); /* one.querySelectorAll("div")  */ show(manyN.length); // 2
<h3>Expecting "one", "oneNested", 3 and 2...</h3>
<div id="one">
  <div id="oneNested"></div>
  <div></div>
</div>



回答5:


This would work, you need to invoke the alias using call() or apply() with the appropriate context.

func.call(context, arg1, arg2, ...) 
func.apply(context, [args]) 

var x = document.querySelectorAll;
x.call(document, 'body');
x.apply(document, ['body']);



回答6:


I took @David Muller's approach and one-lined it using a lambda

let $ = (selector) => document.querySelector(selector);
let $all = (selector) => document.querySelectorAll(selector);

Example:

$('body');
// <body>...</body>



回答7:


function x(expr)
{
    return document.querySelectorAll(expr);
}



回答8:


Here is my take on it. If the selector has multiple matches, return like querySelectorAll. If ony one match is found return like querySelector.

function $(selector) {
  let all = document.querySelectorAll(selector);
  if(all.length == 1) return all[0];
  return all;
}

let one = $('#my-single-element');
let many = $('#multiple-elements li');

2019 update

Today I made a new take on the problem. In this version you can also use a base like this:

let base = document.querySelectorAll('ul');

$$('li'); // All li
$$('li', base); // All li within ul

Functions

function $(selector, base = null) {
  base = (base === null) ? document : base;
  return base.querySelector(selector);
}

function $$(selector, base = null) {
  base = (base === null) ? document : base;
  return base.querySelectorAll(selector);
}



回答9:


function $(selector, base = null) {
  base = (base === null) ? document : base;
  return base.querySelector(selector);
}

function $$(selector, base = null) {
  base = (base === null) ? document : base;
  return base.querySelectorAll(selector);
}

Why not simplier ??? :

let $ = (selector, base = document) => {
  let elements = base.querySelectorAll(selector);
  return (elements.length == 1) ? elements[0] : elements;
}


来源:https://stackoverflow.com/questions/13383886/making-a-short-alias-for-document-queryselectorall

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!