我将运行document.querySelectorAll()很多,并且想要一个简写别名。
var queryAll = document.querySelectorAll
queryAll('body')
TypeError: Illegal invocation
不起作用。鉴于:
document.querySelectorAll('body')
仍然。如何使别名起作用?
答案 0 :(得分:74)
这似乎有效:
var queryAll = document.querySelectorAll.bind(document);
bind
返回对querySelectorAll
函数的引用,将querySelectorAll方法中'this'的上下文更改为文档对象。
仅在IE9 +(以及所有其他浏览器)中支持绑定功能 - https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Function/bind
更新:实际上,您可以创建一系列文档方法的快捷方式,如下所示:
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);
答案 1 :(得分:14)
JavaScript解释器抛出错误,因为应在文档上下文中调用querySelectorAll()
。
当您尝试调用console.log()
别名时,会抛出相同的错误。
所以你需要像这样包装它:
function x(selector) {
return document.querySelectorAll(selector);
}
答案 2 :(得分:7)
这样可行,您需要使用call()
或apply()
使用适当的上下文调用别名。
func.call(context, arg1, arg2, ...)
func.apply(context, [args])
var x = document.querySelectorAll;
x.call(document, 'body');
x.apply(document, ['body']);
答案 3 :(得分:7)
我的解决方案涵盖以下四个用例:
代码:
let doc=document,
qsa=(s,o=doc)=>o.querySelectorAll(s),
qs=(s,o=doc)=>o.querySelector(s);
就参数而言,选择器s
是必需的,但容器元素对象o
是可选的。
用法:
qs("div")
:查询第一个div的整个文档,返回该元素qsa("div")
:查询所有div的整个文档,返回所有这些元素的nodeList qs("div", myContainer)
:在第一个div的myContainer元素内查询,返回该元素qsa("div", myContainer)
:在所有div的myContainer元素内查询,返回所有这些元素的nodeList 为了使代码稍微缩短(但效率不高),qs
代码可以编写如下:
let qs=(s,o=doc)=>qsa(s,o)[0];
上面的代码使用ES6功能(let
,箭头功能和默认参数值)。 ES5等价物是:
var doc=document,
qsa=function(s,o){return(o||doc).querySelectorAll(s);},
qs=function(s,o){return(o||doc).querySelector(s);};
或等效的qs
更短但效率更低的ES5版本:
var qs=function(s,o){return qsa(s,o)[0];};
以下是一个工作演示。为了确保它适用于所有浏览器,它使用ES5版本,但如果你打算使用这个想法,请记住ES6版本更短:
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>
答案 4 :(得分:6)
常见的答案是对$
和$$
使用querySelector
和querySelectorAll
。这个别名模仿了jQuery的一个。
示例:
$ = document.querySelector.bind(document)
$$ = document.querySelectorAll.bind(document)
$('div').style.color = 'blue'
$$('div').forEach(div => div.style.background = 'orange')
&#13;
div {
margin: 2px;
}
&#13;
<div>
test
</div>
<section>
<div>
hello
</div>
<div>
foo
</div>
</section>
&#13;
答案 5 :(得分:4)
我采用了@David Muller的方法,并使用lambda将其排成一行
let $ = (selector) => document.querySelector(selector);
let $all = (selector) => document.querySelectorAll(selector);
示例:
$('body');
// <body>...</body>
答案 6 :(得分:3)
function x(expr)
{
return document.querySelectorAll(expr);
}
答案 7 :(得分:1)
这是我的看法。如果选择器具有多个匹配项,则返回querySelectorAll
。如果发现只有一个匹配项,则返回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年更新
今天,我对这个问题有了新的看法。在此版本中,您还可以使用如下所示的基数:
let base = document.querySelectorAll('ul');
$$('li'); // All li
$$('li', base); // All li within ul
功能
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);
}
答案 8 :(得分:1)
如果您不关心支持没有人应该再使用的古老而糟糕的浏览器,那么您可以这样做:
const $ = (sel, parent = document) => parent.querySelector(sel);
const $$ = (sel, parent = document) => Array.from(parent.querySelectorAll(sel));
以下是一些用法示例:
// find specific element by id
console.log($("#someid"));
// find every element by class, within other element
// NOTE: This is a contrived example to demonstrate the parent search feature.
// If you don't already have the parent in a JavaScript variable, you should
// query via $$("#someparent .someclass") for better performance instead.
console.log($$(".someclass", $("#someparent")));
// find every h1 element
console.log($$("h1"));
// find every h1 element, within other element
console.log($$("h1", $("#exampleparent")));
// alternative way of finding every h1 element within other element
console.log($$("#exampleparent h1"));
// example of finding an element and then checking if it contains another element
console.log($("#exampleparent").contains($("#otherelement")));
// example of finding a bunch of elements and then further filtering them by criteria
// that aren't supported by pure CSS, such as their text content
// NOTE: There WAS a ":contains(text)" selector in CSS3 but it was deprecated from the
// spec because it violated the separation between stylesheets and text content, and you
// can't rely on that CSS selector, which is why you should never use it and should
// instead re-implement it yourself like we do in this example.
// ALSO NOTE: This is just a demonstration of .filter(). I don't recommend using
// "textContent" as a filter. If you need to find specific elements, use their way
// more reliable id/class to find them instead of some arbitrary text content search.
console.log($$("#exampleparent h1").filter(el => el.textContent === "Hello World!"));
我提供的函数使用了大量现代 JS 特性:
const
确保函数变量不会被覆盖。(args) => code with implied return statement
{}
或 return
,因为如果函数体中只有 1 个语句,则可以跳过它们。Array.from()
,它将 querySelectorAll
结果(始终是 NodeList,或空 NodeList)转换为 Array,这基本上是每个开发人员都想要什么。因为这是您访问 .filter()
和其他 Array 函数的方式,这些函数允许您使用干净、简短的代码进一步处理发现的节点。并且 Array.from()
创建所有元素的浅拷贝,这意味着它非常快(它只是将内存引用/指针复制到原始 NodeList 中的每个 Node DOM 元素)。这是一个主要的 API 增强器。如果你关心古代浏览器,你仍然可以使用我的功能,但在你发布网站时使用Babel将现代JS转换为旧ES5。
我的建议是用 ES6 或更高版本编写您的整个网站,然后如果您关心来自 Windows XP 和其他死操作系统的访问者,或者只是 5 年多没有更新浏览器的随机人,请使用 Babel。
但我不推荐使用 Babel。不要担心那些使用旧浏览器的人。这是他们的问题,不是你的。
现代“应用”世界极其深刻地基于网络浏览器、JavaScript 和现代 CSS,如今您的大多数访问者都拥有自动更新的现代浏览器。没有现代浏览器,您基本上无法过现代生活,因为现在有太多网站需要它。
在我看来,从 1993 年开始,希望 网页设计师 浪费时间和理智试图让网站在浏览器上运行的日子已经结束了。是时候了。强>最懒惰的客户/访问者改为更新他们的旧浏览器。这并不难。即使是老旧的操作系统通常也有办法在其上安装新版本的浏览器。而现在没有更新浏览器的人只占百分之一。
例如,世界上最流行的移动/响应式网站框架 Bootstrap 框架只关心支持所有主要浏览器的 2 个最新主要版本(至少 0.5% 的市场份额) .这是他们目前的名单:
我完全同意这一点。我在 2000 年代初期是一名 Web 开发人员,那绝对是地狱。期望让它在一些随机的、愚蠢的用户的古老浏览器上工作是地狱。它带走了 Web 开发的所有乐趣。这让我讨厌并放弃网络开发。因为我 90% 的时间都浪费在浏览器兼容性上。生活不应该是这样。某些客户/访问者懒惰并不是您的错。如今,访问者再也没有借口保持懒惰了。
相反,您应该只定位拥有现代浏览器的用户。这些天基本上是每个人。任何人都没有理由使用旧浏览器。如果他们使用旧浏览器,您的网站应该显示一个又大又胖的横幅,上面写着“请为了自己的利益加入现代世界。下载一个新浏览器。你怎么能用这么旧的浏览器过正常的生活?你是穴居人时代的时间旅行者吗?”。
人们没有借口再使用旧浏览器:
如今,大多数人都拥有完全最新且自动更新的浏览器。事实就是如此。
所以是的......网站设计师只为迎合旧浏览器而受苦受难的日子已经结束。所以我建议大家在自己的网站上使用 ES6 和 CSS3,让网页设计第一次成为一种乐趣。
希望你喜欢我提供的 ES6 功能!
答案 9 :(得分:0)
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); }
为什么不简单??? :
let $ = (selector, base = document) => {
let elements = base.querySelectorAll(selector);
return (elements.length == 1) ? elements[0] : elements;
}