Javascript 在 IE 中比在 Chrome 浏览器中循环更快
Javascript loop way faster in IE than Chrome browsers
我在旧的 aspx 网页上的 JS 文件中有一个简单的 for 循环:
function SaveCurrentFilterDisplay() {
var currentFilterCode = document.getElementById('curfilt').value;
var currentFilterList, currentFilterDisplay;
var i, str;
if (currentFilterCode != '') {
currentFilterList = document.getElementById(currentFilterCode);
currentFilterDisplay = document.getElementById(currentFilterCode + '_display');
//save the previous filter text names
//alert(currentFilterCode + ': ' + currentFilterList.length);
if (currentFilterList.length) {
//multi-select list
str = '';
for (i = 0; i < currentFilterList.length; i++) {
if (currentFilterList.options[i].selected) {
if (str.length > 0) {
str = str + ', '
}
str = str + currentFilterList.options[i].text;
}
}
} else {
//text field
str = currentFilterList.value;
}
alert('finished looping');
currentFilterDisplay.value = str;
}
return true;
}
有时这个循环要循环将近 50,000 次。其他的也就几百或者更少。
令我困惑的是,当循环必须循环 50,000 次并且我 运行 在 Chrome 中执行此操作时,大约需要 2 分钟。但是当我在 IE 中做完全相同的事情时,只需要几秒钟,有时甚至看起来是瞬间的。
我想知道是否有关于基于 Chrome 的浏览器如何处理 Javascript 的解释?
编辑:也许还有关于如何优化它的任何建议,以便在 Chrome 中不需要 2 分钟?
编辑 2:我更新了我的问题以显示整个功能。当我使用 Chrome 开发工具单步执行函数时,方法中的所有语句都会立即执行,但是当我单步执行循环时,需要 2 分钟才能触发警报语句,因此 是 需要 2 分钟的循环。
这里有一些 HTML 显示了 currentFilterList 指向的内容:
<select id="ID" name="adv" multiple="true">
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</select>
举个例子,currentFilterCode = "ID"。这使得 currentFilterList 设置为上面的 select 列表(由于明显的原因比真实列表短得多)。
最终编辑: 在评论的帮助下,我post 解决了我面临的特定问题。这不是处理类似情况的最佳方法,但它在我正在处理的应用程序的限制范围内有效。我选择了另一个答案作为解决方案,因为它是处理类似情况的方法。
首先,当我试图解决我在优化时遇到的难看的遗留代码时,在评论中向所有与我一起工作的人大声疾呼。多亏了他们,我找到了解决方案。
问题与从循环中巨大 select 的第 ith 选项获取属性有关。
我找到了这篇优秀的文章:https://idiallo.com/javascript/minimize-lookups-in-for-loops
其中提到了几种优化循环访问 DOM 元素的方法,就像我正在使用的那样。作者提到了创建和重新分配变量是如何减慢速度的(阅读真实的东西,我不公正地对待它)。解决方法是在循环外创建变量并使用它们。应用更改后,我得到以下信息:
function SaveCurrentFilterDisplay() {
var currentFilterCode = document.getElementById('curfilt').value;
var currentFilterList, currentFilterDisplay;
var i = 0, str, numOptions, selectedOptions;
if (currentFilterCode != '') {
currentFilterList = document.getElementById(currentFilterCode);
currentFilterDisplay = document.getElementById(currentFilterCode + '_display');
selectedOptions = currentFilterList.selectedOptions;
numOptions = selectedOptions.length;
if (selectedOptions.length) {
str = '';
for (; i < numOptions; i++) {
if (str.length > 0) {
str = str + ', '
}
str = str + selectedOptions[i].text;
}
} else {
str = currentFilterList.value;
}
currentFilterDisplay.value = str;
}
}
作者提到性能提升可以忽略不计。然而,就像阅读本文的每个人一样 post,他可能没有考虑过遍历 50,000 个选项的长 select 列表!
这现在在不到一秒的时间内遍历了 50,000 个项目!
编辑:编辑为使用评论中提到的 selectedOptions。这就是我让这个旧网页正常工作的方式。显然它不是最好的解决方案,但它在应用程序的其余部分对我施加的限制内工作。
既然可以使用选择器,为什么还要循环查找选择呢?使用 map 和 join 构建所选值的字符串。
document.querySelector("#select1").addEventListener("change", () => {
const out = [...document.querySelectorAll('#select1 option:checked')].map(x => x.text);
console.log(out.join(', '));
});
/*
document.querySelector("#select1").addEventListener("change", function() {
var out = Array.from(document.querySelectorAll('#select1 option:checked')).map(function(x) { return x.text; });
console.log(out.join(', '));
});
*/
<select id="select1" multiple>
<option>FOO1</option>
<option>FOO2</option>
<option>FOO3</option>
<option>FOO4</option>
<option>FOO5</option>
<option>FOO6</option>
<option>FOO7</option>
<option>FOO8</option>
<option>FOO9</option>
<option>FOO10</option>
</select>
或选择选项并映射和加入
document.querySelector("#select1").addEventListener("change", () => {
var out = [...document.querySelector('#select1').selectedOptions].map(x => x.text);
console.log(out.join(', '));
});
<select id="select1" multiple>
<option>FOO1</option>
<option>FOO2</option>
<option>FOO3</option>
<option>FOO4</option>
<option>FOO5</option>
<option>FOO6</option>
<option>FOO7</option>
<option>FOO8</option>
<option>FOO9</option>
<option>FOO10</option>
</select>
我在旧的 aspx 网页上的 JS 文件中有一个简单的 for 循环:
function SaveCurrentFilterDisplay() {
var currentFilterCode = document.getElementById('curfilt').value;
var currentFilterList, currentFilterDisplay;
var i, str;
if (currentFilterCode != '') {
currentFilterList = document.getElementById(currentFilterCode);
currentFilterDisplay = document.getElementById(currentFilterCode + '_display');
//save the previous filter text names
//alert(currentFilterCode + ': ' + currentFilterList.length);
if (currentFilterList.length) {
//multi-select list
str = '';
for (i = 0; i < currentFilterList.length; i++) {
if (currentFilterList.options[i].selected) {
if (str.length > 0) {
str = str + ', '
}
str = str + currentFilterList.options[i].text;
}
}
} else {
//text field
str = currentFilterList.value;
}
alert('finished looping');
currentFilterDisplay.value = str;
}
return true;
}
有时这个循环要循环将近 50,000 次。其他的也就几百或者更少。
令我困惑的是,当循环必须循环 50,000 次并且我 运行 在 Chrome 中执行此操作时,大约需要 2 分钟。但是当我在 IE 中做完全相同的事情时,只需要几秒钟,有时甚至看起来是瞬间的。
我想知道是否有关于基于 Chrome 的浏览器如何处理 Javascript 的解释?
编辑:也许还有关于如何优化它的任何建议,以便在 Chrome 中不需要 2 分钟?
编辑 2:我更新了我的问题以显示整个功能。当我使用 Chrome 开发工具单步执行函数时,方法中的所有语句都会立即执行,但是当我单步执行循环时,需要 2 分钟才能触发警报语句,因此 是 需要 2 分钟的循环。
这里有一些 HTML 显示了 currentFilterList 指向的内容:
<select id="ID" name="adv" multiple="true">
<option value="1">Option 1</option>
<option value="2">Option 2</option>
<option value="3">Option 3</option>
</select>
举个例子,currentFilterCode = "ID"。这使得 currentFilterList 设置为上面的 select 列表(由于明显的原因比真实列表短得多)。
最终编辑: 在评论的帮助下,我post 解决了我面临的特定问题。这不是处理类似情况的最佳方法,但它在我正在处理的应用程序的限制范围内有效。我选择了另一个答案作为解决方案,因为它是处理类似情况的方法。
首先,当我试图解决我在优化时遇到的难看的遗留代码时,在评论中向所有与我一起工作的人大声疾呼。多亏了他们,我找到了解决方案。
问题与从循环中巨大 select 的第 ith 选项获取属性有关。
我找到了这篇优秀的文章:https://idiallo.com/javascript/minimize-lookups-in-for-loops
其中提到了几种优化循环访问 DOM 元素的方法,就像我正在使用的那样。作者提到了创建和重新分配变量是如何减慢速度的(阅读真实的东西,我不公正地对待它)。解决方法是在循环外创建变量并使用它们。应用更改后,我得到以下信息:
function SaveCurrentFilterDisplay() {
var currentFilterCode = document.getElementById('curfilt').value;
var currentFilterList, currentFilterDisplay;
var i = 0, str, numOptions, selectedOptions;
if (currentFilterCode != '') {
currentFilterList = document.getElementById(currentFilterCode);
currentFilterDisplay = document.getElementById(currentFilterCode + '_display');
selectedOptions = currentFilterList.selectedOptions;
numOptions = selectedOptions.length;
if (selectedOptions.length) {
str = '';
for (; i < numOptions; i++) {
if (str.length > 0) {
str = str + ', '
}
str = str + selectedOptions[i].text;
}
} else {
str = currentFilterList.value;
}
currentFilterDisplay.value = str;
}
}
作者提到性能提升可以忽略不计。然而,就像阅读本文的每个人一样 post,他可能没有考虑过遍历 50,000 个选项的长 select 列表!
这现在在不到一秒的时间内遍历了 50,000 个项目!
编辑:编辑为使用评论中提到的 selectedOptions。这就是我让这个旧网页正常工作的方式。显然它不是最好的解决方案,但它在应用程序的其余部分对我施加的限制内工作。
既然可以使用选择器,为什么还要循环查找选择呢?使用 map 和 join 构建所选值的字符串。
document.querySelector("#select1").addEventListener("change", () => {
const out = [...document.querySelectorAll('#select1 option:checked')].map(x => x.text);
console.log(out.join(', '));
});
/*
document.querySelector("#select1").addEventListener("change", function() {
var out = Array.from(document.querySelectorAll('#select1 option:checked')).map(function(x) { return x.text; });
console.log(out.join(', '));
});
*/
<select id="select1" multiple>
<option>FOO1</option>
<option>FOO2</option>
<option>FOO3</option>
<option>FOO4</option>
<option>FOO5</option>
<option>FOO6</option>
<option>FOO7</option>
<option>FOO8</option>
<option>FOO9</option>
<option>FOO10</option>
</select>
或选择选项并映射和加入
document.querySelector("#select1").addEventListener("change", () => {
var out = [...document.querySelector('#select1').selectedOptions].map(x => x.text);
console.log(out.join(', '));
});
<select id="select1" multiple>
<option>FOO1</option>
<option>FOO2</option>
<option>FOO3</option>
<option>FOO4</option>
<option>FOO5</option>
<option>FOO6</option>
<option>FOO7</option>
<option>FOO8</option>
<option>FOO9</option>
<option>FOO10</option>
</select>