问题表明 JS 和 jQuery 中的那些代码行做同样的事情,但他们没有!
因此,我将答案分为两部分:
1。哪一个 JS/jQuery 对实际上在做同样的事情,它们的表现如何?
# suggested JavaScript version
parent.addEventListener("click", function(e) {
if (e.target === child) { code }
});
# correct equivalent jQuery version
$(parent).on("click", function(e) {
if (e.target === child) { code }
});
性能
短:性能差异很小,没关系。
Long:两个版本看起来几乎一样。 jQuery 变体有点慢,但可以忽略不计。如果我喜欢使用 jQuery(例如方法链接)或者想使用 jQuery 来提高可读性/一致性,我会使用 jQuery 版本。
出于速度原因使用 JavaScript 版本同时捍卫/促进/提倡在该项目中使用 jQuery 将是利益冲突。
2。 OP 的 jQuery 行有什么问题?
# OP’s version: jQuery selector/delegate syntax
$(parent).on("click", child, function() { code });
首先,jQuery 的选择器/委托语法并没有像 OP 认为的那样做。你很有可能落入同一个陷阱——就像我一样。
其次,jQuery 文档没有对这个问题提供任何启示,而是培养了错误的信念,即该语法的作用和用途。例如。将其称为“委托语法”,而实际上委托处理程序可以而且应该更好地使用“正常”语法进行注册。
第三,jQuery 错误地使用选择器/委托语法会带来额外的性能损失,远远超过上面提到的正确 jQuery 版本的轻微损失。
总而言之:尽管这条线很短,看起来很漂亮,并且可能会在您的测试用例中产生正确的结果,但它还是有缺陷、记录不充分并浪费资源。
这个答案的其余部分通过示例显示 jQuery 做错了什么:
我想我们都同意一个事件最多应该调用一次处理程序。通过以下代码示例,我将向您展示单个事件如何触发处理程序的 3 次调用。
单击内部框以查看 jQuery 如何为目标和处理程序元素之间的所有匹配元素添加单个事件。我不知道这种机制的合理用例,即使这种意外和奇怪的行为没有影响到你,jQuery 为它所做的额外工作仍然存在。
它要么没有效果,只是消耗 CPU 周期,要么会产生错误。
let lastEvent;
function analyze(tag, event) {
const oe = event.originalEvent;
console.log(`${tag}: Event on ${event.target.id} is ${lastEvent === oe ? 'repeated' : 'new'}.`);
lastEvent = oe;
}
body.addEventListener('click', event =>
console.log('click', event.target.id));
$(body).on('click', analyze.bind(null, '$click'));
$(body).on('click', '.hit', analyze.bind(null, '$delegateClick'));
div {
margin: 20px;
border: solid black 2px;
}
#inner {
height: 80px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body id=body>
<div id=outer class=hit>
<div id=middle class=hit>
<div id=inner class=hit>
</div>
</div>
</div>
</body>