Javascript IE11 问题
Javascript issue with IE11
我的应用程序在 IE9 之前运行良好,现在当我将其升级到 IE11 时它停止运行。这是一个示例 html 和 js .
问题
在第一个 运行 即。 加载 效果很好。但是当我 select PDA 品牌时,第二个下拉菜单的所有选项都变成空白。
在控制台中,对象 clonedOptions
上存在脚本错误 Invalid Calling Object error
。
function dynamicSelect(id1, id2) {
//alert("Everytime")
// Browser and feature tests to see if there is enough W3C DOM support
// Obtain references to both select boxes
var sel1 = document.getElementById(id1);
var sel2 = document.getElementById(id2);
// Clone the dynamic select box
var clone = sel2.cloneNode(true);
// Obtain references to all cloned options
var clonedOptions = clone.getElementsByTagName("option");
// Onload init: call a generic function to display the related options in the dynamic select box
refreshDynamicSelectOptions(sel1, sel2, clonedOptions);
// Onchange of the main select box: call a generic function to display the related options in the dynamic select box
sel1.onchange = function() {
refreshDynamicSelectOptions(sel1, sel2, clonedOptions);
};
}
function refreshDynamicSelectOptions(sel1, sel2, clonedOptions) {
while (sel2.options.length) {
sel2.remove(0);
}
//alert(sel1.options[sel1.selectedIndex].value)
// Create regular expression objects for "select" and the value of the selected option of the main select box as class names
var pattern1 = /( |^)(select)( |$)/;
var pattern2 = new RegExp("( |^)(" + sel1.options[sel1.selectedIndex].value + ")( |$)");
// Iterate through all cloned options
//alert(clonedOptions.length);
for (var i = 0; i < clonedOptions.length; i++) {
// If the classname of a cloned option either equals "select" or equals the value of the selected option of the main select box
if (clonedOptions[i].className.match(pattern1) || clonedOptions[i].className.match(pattern2)) {
// Clone the option from the hidden option pool and append it to the dynamic select box
//alert("Did match")
sel2.appendChild(clonedOptions[i].cloneNode(true));
//alert(sel2.options[1]);
}
}
}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>dynamic selectbox example</title>
<script type="text/javascript" src="unobtrusivedynamicselect_ex5.js"></script>
</head>
<body>
<form action="#">
<div>
<select id="pda-brand">
<option value="select">Select PDA brand...</option>
<option value="dell">Dell</option>
<option value="hp">HP</option>
<option value="palmone">PalmOne</option>
</select>
<select id="pda-type">
<option class="select" value="select">Select PDA type...</option>
<option class="dell" value="aximx30">Axim X30</option>
<option class="dell" value="aximx50">Axim X50</option>
<option class="hp" value="ipaqhx2750">iPAQ hx2750</option>
<option class="hp" value="ipaqrx3715">iPAQ rx3715</option>
<option class="hp" value="ipaqrz1710">iPAQ rz1710</option>
<option class="palmone" value="tungstene2">Tungsten E2</option>
<option class="palmone" value="tungstent5">Tungsten T5</option>
<option class="palmone" value="zire72">Zire 72</option>
</select>
<script type="text/javascript">
window.onload = function(e) {
dynamicSelect("pda-brand", "pda-type");
}
</script>
</div>
</form>
</body>
</html>
问题线
在下面的 loc 中,对于 clonedOptions,我收到无效调用对象错误。
for (var i = 0; i < clonedOptions.length; i++) {
我可以在 IE-11 中使用它,请自行尝试。
据我了解,问题是:
var clone = sel2.cloneNode(true);
var clonedOptions = clone.getElementsByTagName("option");
clonedOptions
可能是对 clone
的 children 的引用,标签名称为 option
sel1.onchange = function() {
refreshDynamicSelectOptions(sel1, sel2, clonedOptions);
};
在此函数中有对 clonedOptions
的引用,但没有对 clone
的引用。所以 clone
可能是 garbageCollected,因为 IE 找不到任何保留它的理由。 clonedOptions
保留对不存在的集合的引用。
你可以用你自己的方式更正,我只是传递 clone
而不是 clonedOptions
并且它适用于我 IE11
function dynamicSelect(id1, id2) {
//alert("Everytime")
// Browser and feature tests to see if there is enough W3C DOM support
// Obtain references to both select boxes
var sel1 = document.getElementById(id1);
var sel2 = document.getElementById(id2);
// Clone the dynamic select box // Obtain references to all cloned options
var clone = sel2.cloneNode(true);
// Onload init: call a generic function to display the related options in the dynamic select box
refreshDynamicSelectOptions(sel1, sel2, clone);
// Onchange of the main select box: call a generic function to display the related options in the dynamic select box
sel1.onchange = function() {
refreshDynamicSelectOptions(sel1, sel2, clone);
};
}
function refreshDynamicSelectOptions(sel1, sel2, clone) {
var clonedOptions = clone.getElementsByTagName("option");
while (sel2.options.length) {
sel2.remove(0);
}
//alert(sel1.options[sel1.selectedIndex].value)
// Create regular expression objects for "select" and the value of the selected option of the main select box as class names
var pattern1 = /( |^)(select)( |$)/;
var pattern2 = new RegExp("( |^)(" + sel1.options[sel1.selectedIndex].value + ")( |$)");
// Iterate through all cloned options
//alert(clonedOptions.length);
for (var i = 0; i < clonedOptions.length; i++) {
// If the classname of a cloned option either equals "select" or equals the value of the selected option of the main select box
if (clonedOptions[i].className.match(pattern1) || clonedOptions[i].className.match(pattern2)) {
// Clone the option from the hidden option pool and append it to the dynamic select box
//alert("Did match")
sel2.appendChild(clonedOptions[i].cloneNode(true));
//alert(sel2.options[1]);
}
}
}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>dynamic selectbox example</title>
<script type="text/javascript" src="unobtrusivedynamicselect_ex5.js"></script>
</head>
<body>
<form action="#">
<div>
<select id="pda-brand">
<option value="select">Select PDA brand...</option>
<option value="dell">Dell</option>
<option value="hp">HP</option>
<option value="palmone">PalmOne</option>
</select>
<select id="pda-type">
<option class="select" value="select">Select PDA type...</option>
<option class="dell" value="aximx30">Axim X30</option>
<option class="dell" value="aximx50">Axim X50</option>
<option class="hp" value="ipaqhx2750">iPAQ hx2750</option>
<option class="hp" value="ipaqrx3715">iPAQ rx3715</option>
<option class="hp" value="ipaqrz1710">iPAQ rz1710</option>
<option class="palmone" value="tungstene2">Tungsten E2</option>
<option class="palmone" value="tungstent5">Tungsten T5</option>
<option class="palmone" value="zire72">Zire 72</option>
</select>
<script type="text/javascript">
window.onload = function(e) {
dynamicSelect("pda-brand", "pda-type");
}
</script>
</div>
</form>
</body>
</html>
我认为问题在于您使用的是 getElementsByTagName
,其中 returns 是一个实时列表,这意味着如果从 DOM 中删除了某个项目,它也会从 DOM 中删除列表,因此有资格进行垃圾收集。参见 https://developer.mozilla.org/en-US/docs/Web/API/Element/getElementsByTagName
The returned list is live, meaning that it updates itself with the DOM tree automatically.
下面的例子会解释我的意思
var ps = document.body.getElementsByTagName('p');
var ps2 = document.body.querySelectorAll('p');
console.log(ps.length); // 3
document.body.removeChild(ps[0]);
console.log(ps.length); // 2
console.log(ps2.length); // 3
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
我没有最新的 IE,但我有一种强烈的感觉,如果您使用 clone.querySelectorAll("option")
,您将不会遇到同样的问题,因为自从列出来 returns 未直播。
function dynamicSelect(id1, id2) {
//alert("Everytime")
// Browser and feature tests to see if there is enough W3C DOM support
// Obtain references to both select boxes
var sel1 = document.getElementById(id1);
var sel2 = document.getElementById(id2);
// Clone the dynamic select box
var clone = sel2.cloneNode(true);
// Obtain references to all cloned options
var clonedOptions = clone.querySelectorAll("option");
// Onload init: call a generic function to display the related options in the dynamic select box
refreshDynamicSelectOptions(sel1, sel2, clonedOptions);
// Onchange of the main select box: call a generic function to display the related options in the dynamic select box
sel1.onchange = function() {
refreshDynamicSelectOptions(sel1, sel2, clonedOptions);
};
}
function refreshDynamicSelectOptions(sel1, sel2, clonedOptions) {
while (sel2.options.length) {
sel2.remove(0);
}
//alert(sel1.options[sel1.selectedIndex].value)
// Create regular expression objects for "select" and the value of the selected option of the main select box as class names
var pattern1 = /( |^)(select)( |$)/;
var pattern2 = new RegExp("( |^)(" + sel1.options[sel1.selectedIndex].value + ")( |$)");
// Iterate through all cloned options
//alert(clonedOptions.length);
for (var i = 0; i < clonedOptions.length; i++) {
// If the classname of a cloned option either equals "select" or equals the value of the selected option of the main select box
if (clonedOptions[i].className.match(pattern1) || clonedOptions[i].className.match(pattern2)) {
// Clone the option from the hidden option pool and append it to the dynamic select box
//alert("Did match")
sel2.appendChild(clonedOptions[i].cloneNode(true));
//alert(sel2.options[1]);
}
}
}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>dynamic selectbox example</title>
<script type="text/javascript" src="unobtrusivedynamicselect_ex5.js"></script>
</head>
<body>
<form action="#">
<div>
<select id="pda-brand">
<option value="select">Select PDA brand...</option>
<option value="dell">Dell</option>
<option value="hp">HP</option>
<option value="palmone">PalmOne</option>
</select>
<select id="pda-type">
<option class="select" value="select">Select PDA type...</option>
<option class="dell" value="aximx30">Axim X30</option>
<option class="dell" value="aximx50">Axim X50</option>
<option class="hp" value="ipaqhx2750">iPAQ hx2750</option>
<option class="hp" value="ipaqrx3715">iPAQ rx3715</option>
<option class="hp" value="ipaqrz1710">iPAQ rz1710</option>
<option class="palmone" value="tungstene2">Tungsten E2</option>
<option class="palmone" value="tungstent5">Tungsten T5</option>
<option class="palmone" value="zire72">Zire 72</option>
</select>
<script type="text/javascript">
window.onload = function(e) {
dynamicSelect("pda-brand", "pda-type");
}
</script>
</div>
</form>
</body>
</html>
我的应用程序在 IE9 之前运行良好,现在当我将其升级到 IE11 时它停止运行。这是一个示例 html 和 js .
问题
在第一个 运行 即。 加载 效果很好。但是当我 select PDA 品牌时,第二个下拉菜单的所有选项都变成空白。
在控制台中,对象 clonedOptions
上存在脚本错误 Invalid Calling Object error
。
function dynamicSelect(id1, id2) {
//alert("Everytime")
// Browser and feature tests to see if there is enough W3C DOM support
// Obtain references to both select boxes
var sel1 = document.getElementById(id1);
var sel2 = document.getElementById(id2);
// Clone the dynamic select box
var clone = sel2.cloneNode(true);
// Obtain references to all cloned options
var clonedOptions = clone.getElementsByTagName("option");
// Onload init: call a generic function to display the related options in the dynamic select box
refreshDynamicSelectOptions(sel1, sel2, clonedOptions);
// Onchange of the main select box: call a generic function to display the related options in the dynamic select box
sel1.onchange = function() {
refreshDynamicSelectOptions(sel1, sel2, clonedOptions);
};
}
function refreshDynamicSelectOptions(sel1, sel2, clonedOptions) {
while (sel2.options.length) {
sel2.remove(0);
}
//alert(sel1.options[sel1.selectedIndex].value)
// Create regular expression objects for "select" and the value of the selected option of the main select box as class names
var pattern1 = /( |^)(select)( |$)/;
var pattern2 = new RegExp("( |^)(" + sel1.options[sel1.selectedIndex].value + ")( |$)");
// Iterate through all cloned options
//alert(clonedOptions.length);
for (var i = 0; i < clonedOptions.length; i++) {
// If the classname of a cloned option either equals "select" or equals the value of the selected option of the main select box
if (clonedOptions[i].className.match(pattern1) || clonedOptions[i].className.match(pattern2)) {
// Clone the option from the hidden option pool and append it to the dynamic select box
//alert("Did match")
sel2.appendChild(clonedOptions[i].cloneNode(true));
//alert(sel2.options[1]);
}
}
}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>dynamic selectbox example</title>
<script type="text/javascript" src="unobtrusivedynamicselect_ex5.js"></script>
</head>
<body>
<form action="#">
<div>
<select id="pda-brand">
<option value="select">Select PDA brand...</option>
<option value="dell">Dell</option>
<option value="hp">HP</option>
<option value="palmone">PalmOne</option>
</select>
<select id="pda-type">
<option class="select" value="select">Select PDA type...</option>
<option class="dell" value="aximx30">Axim X30</option>
<option class="dell" value="aximx50">Axim X50</option>
<option class="hp" value="ipaqhx2750">iPAQ hx2750</option>
<option class="hp" value="ipaqrx3715">iPAQ rx3715</option>
<option class="hp" value="ipaqrz1710">iPAQ rz1710</option>
<option class="palmone" value="tungstene2">Tungsten E2</option>
<option class="palmone" value="tungstent5">Tungsten T5</option>
<option class="palmone" value="zire72">Zire 72</option>
</select>
<script type="text/javascript">
window.onload = function(e) {
dynamicSelect("pda-brand", "pda-type");
}
</script>
</div>
</form>
</body>
</html>
问题线
在下面的 loc 中,对于 clonedOptions,我收到无效调用对象错误。
for (var i = 0; i < clonedOptions.length; i++) {
我可以在 IE-11 中使用它,请自行尝试。
据我了解,问题是:
var clone = sel2.cloneNode(true);
var clonedOptions = clone.getElementsByTagName("option");
clonedOptions
可能是对 clone
的 children 的引用,标签名称为 option
sel1.onchange = function() {
refreshDynamicSelectOptions(sel1, sel2, clonedOptions);
};
在此函数中有对 clonedOptions
的引用,但没有对 clone
的引用。所以 clone
可能是 garbageCollected,因为 IE 找不到任何保留它的理由。 clonedOptions
保留对不存在的集合的引用。
你可以用你自己的方式更正,我只是传递 clone
而不是 clonedOptions
并且它适用于我 IE11
function dynamicSelect(id1, id2) {
//alert("Everytime")
// Browser and feature tests to see if there is enough W3C DOM support
// Obtain references to both select boxes
var sel1 = document.getElementById(id1);
var sel2 = document.getElementById(id2);
// Clone the dynamic select box // Obtain references to all cloned options
var clone = sel2.cloneNode(true);
// Onload init: call a generic function to display the related options in the dynamic select box
refreshDynamicSelectOptions(sel1, sel2, clone);
// Onchange of the main select box: call a generic function to display the related options in the dynamic select box
sel1.onchange = function() {
refreshDynamicSelectOptions(sel1, sel2, clone);
};
}
function refreshDynamicSelectOptions(sel1, sel2, clone) {
var clonedOptions = clone.getElementsByTagName("option");
while (sel2.options.length) {
sel2.remove(0);
}
//alert(sel1.options[sel1.selectedIndex].value)
// Create regular expression objects for "select" and the value of the selected option of the main select box as class names
var pattern1 = /( |^)(select)( |$)/;
var pattern2 = new RegExp("( |^)(" + sel1.options[sel1.selectedIndex].value + ")( |$)");
// Iterate through all cloned options
//alert(clonedOptions.length);
for (var i = 0; i < clonedOptions.length; i++) {
// If the classname of a cloned option either equals "select" or equals the value of the selected option of the main select box
if (clonedOptions[i].className.match(pattern1) || clonedOptions[i].className.match(pattern2)) {
// Clone the option from the hidden option pool and append it to the dynamic select box
//alert("Did match")
sel2.appendChild(clonedOptions[i].cloneNode(true));
//alert(sel2.options[1]);
}
}
}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>dynamic selectbox example</title>
<script type="text/javascript" src="unobtrusivedynamicselect_ex5.js"></script>
</head>
<body>
<form action="#">
<div>
<select id="pda-brand">
<option value="select">Select PDA brand...</option>
<option value="dell">Dell</option>
<option value="hp">HP</option>
<option value="palmone">PalmOne</option>
</select>
<select id="pda-type">
<option class="select" value="select">Select PDA type...</option>
<option class="dell" value="aximx30">Axim X30</option>
<option class="dell" value="aximx50">Axim X50</option>
<option class="hp" value="ipaqhx2750">iPAQ hx2750</option>
<option class="hp" value="ipaqrx3715">iPAQ rx3715</option>
<option class="hp" value="ipaqrz1710">iPAQ rz1710</option>
<option class="palmone" value="tungstene2">Tungsten E2</option>
<option class="palmone" value="tungstent5">Tungsten T5</option>
<option class="palmone" value="zire72">Zire 72</option>
</select>
<script type="text/javascript">
window.onload = function(e) {
dynamicSelect("pda-brand", "pda-type");
}
</script>
</div>
</form>
</body>
</html>
我认为问题在于您使用的是 getElementsByTagName
,其中 returns 是一个实时列表,这意味着如果从 DOM 中删除了某个项目,它也会从 DOM 中删除列表,因此有资格进行垃圾收集。参见 https://developer.mozilla.org/en-US/docs/Web/API/Element/getElementsByTagName
The returned list is live, meaning that it updates itself with the DOM tree automatically.
下面的例子会解释我的意思
var ps = document.body.getElementsByTagName('p');
var ps2 = document.body.querySelectorAll('p');
console.log(ps.length); // 3
document.body.removeChild(ps[0]);
console.log(ps.length); // 2
console.log(ps2.length); // 3
<p>Hello</p>
<p>Hello</p>
<p>Hello</p>
我没有最新的 IE,但我有一种强烈的感觉,如果您使用 clone.querySelectorAll("option")
,您将不会遇到同样的问题,因为自从列出来 returns 未直播。
function dynamicSelect(id1, id2) {
//alert("Everytime")
// Browser and feature tests to see if there is enough W3C DOM support
// Obtain references to both select boxes
var sel1 = document.getElementById(id1);
var sel2 = document.getElementById(id2);
// Clone the dynamic select box
var clone = sel2.cloneNode(true);
// Obtain references to all cloned options
var clonedOptions = clone.querySelectorAll("option");
// Onload init: call a generic function to display the related options in the dynamic select box
refreshDynamicSelectOptions(sel1, sel2, clonedOptions);
// Onchange of the main select box: call a generic function to display the related options in the dynamic select box
sel1.onchange = function() {
refreshDynamicSelectOptions(sel1, sel2, clonedOptions);
};
}
function refreshDynamicSelectOptions(sel1, sel2, clonedOptions) {
while (sel2.options.length) {
sel2.remove(0);
}
//alert(sel1.options[sel1.selectedIndex].value)
// Create regular expression objects for "select" and the value of the selected option of the main select box as class names
var pattern1 = /( |^)(select)( |$)/;
var pattern2 = new RegExp("( |^)(" + sel1.options[sel1.selectedIndex].value + ")( |$)");
// Iterate through all cloned options
//alert(clonedOptions.length);
for (var i = 0; i < clonedOptions.length; i++) {
// If the classname of a cloned option either equals "select" or equals the value of the selected option of the main select box
if (clonedOptions[i].className.match(pattern1) || clonedOptions[i].className.match(pattern2)) {
// Clone the option from the hidden option pool and append it to the dynamic select box
//alert("Did match")
sel2.appendChild(clonedOptions[i].cloneNode(true));
//alert(sel2.options[1]);
}
}
}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>dynamic selectbox example</title>
<script type="text/javascript" src="unobtrusivedynamicselect_ex5.js"></script>
</head>
<body>
<form action="#">
<div>
<select id="pda-brand">
<option value="select">Select PDA brand...</option>
<option value="dell">Dell</option>
<option value="hp">HP</option>
<option value="palmone">PalmOne</option>
</select>
<select id="pda-type">
<option class="select" value="select">Select PDA type...</option>
<option class="dell" value="aximx30">Axim X30</option>
<option class="dell" value="aximx50">Axim X50</option>
<option class="hp" value="ipaqhx2750">iPAQ hx2750</option>
<option class="hp" value="ipaqrx3715">iPAQ rx3715</option>
<option class="hp" value="ipaqrz1710">iPAQ rz1710</option>
<option class="palmone" value="tungstene2">Tungsten E2</option>
<option class="palmone" value="tungstent5">Tungsten T5</option>
<option class="palmone" value="zire72">Zire 72</option>
</select>
<script type="text/javascript">
window.onload = function(e) {
dynamicSelect("pda-brand", "pda-type");
}
</script>
</div>
</form>
</body>
</html>