NB我读过一些关于JS引擎优化的文章,但大部分都是技术性的,我无法理解,无法适用于这个问题。我也知道不是所有的引擎都是一样的。我想,我对V8和Rhino的处理特别感兴趣。
如果我建立一个表,然后是行,然后是单元格... ... 然后我想把相同的键事件监听器放在所有这些单元格上。
不仅为每个单元格创建这些监听器需要一定的时间,这对一个大表来说可能会很重要,而且我假设每个监听器函数都是单独存储的,尽管每个监听器函数实际上都是相同的。
我可以使用的另一种关键事件监听方法是将一个关键事件监听器置于 TABLE
,并在跑步过程中锻炼身体,在每一 keydown
事件,哪个单元格触发了这个事件。我可以通过
let elementOfInterest = document.activeElement;
"获取文档中的当前焦点元素 "从 此处.
根据我的实验,如果你在一个表格单元格里面打字,这个 TD
确实有焦点,并且确实被上述调用返回。
这样一来,我只需要创建一个监听器,我想这样会更快,占用的内存更少。唯一(非常)轻微的缺点是,必须花费时间通过上述调用来获取这个 "活动元素"。而且,也有可能,某些东西会以意想不到的方式抢占焦点--很明显,如果你想监听一个单元格中的文本变化,最不容易出错的技术一定是使用一个连接到该单元格的监听器。
但我只是想知道:也许Javascript比这更聪明:也许如果你创建100个独立的单元格监听器,某个地方会将它们识别为 "都是一样的",并在内存中只做一个函数。比如说,这就是你通常期望从Java编译器中得到的优化。
这样的优化有没有发生过?这样的情况下,Javascript到底有多聪明?或者它只是 "脚本,就是这样":你看到的就是你得到的?
语言本身的语义不允许两个函数表达式 "合并 "成一个,即使它们在功能上等同。
> a = function(){return 'foo'};
ƒ (){return 'foo'}
> b = function(){return 'foo'};
ƒ (){return 'foo'}
> a === b
false
此外,当你开始考虑函数的闭包时,事情就变得更加棘手了(例如,它使用的外部名称)。
所以,不,这种情况不会发生。
然而,对于你的用例,有两种优化方法。
event.target
(最好不要 document.activeElement
),以弄清它最初的目标是什么地方(以及 event.currentTarget
将是处理程序所在的节点)document
是一个有效的目标),你可以定义一次函数(假设它不需要在任何动态变化的变量上关闭),然后再次使用 event.target
,例如 event.target.dataset
来弄清你所处理的数据。下面,用一个片段来演示这两者。
function createButton(parent, datum) {
const btn = document.createElement("button");
btn.dataset.datum = datum;
btn.innerHTML = datum;
parent.appendChild(btn);
return btn;
}
function eventHandler(event) {
if(event.target.tagName !== "BUTTON") return;
const msg = `real target: ${event.target} (datum="${event.target.dataset.datum}")\ncurrent target: ${event.currentTarget}`;
alert(msg);
}
const p2 = document.getElementById("parent2");
// bubbling listener
const p1 = document.getElementById("parent1");
p1.addEventListener("click", eventHandler, false);
for(var i = 0; i < 10; i++) {
createButton(p1, "p1-" + i);
}
// same function on multiple elements
for(var i = 0; i < 10; i++) {
createButton(p2, "p2-" + i).addEventListener("click", eventHandler, false);
}
<div id="parent1"></div>
<div id="parent2"></div>