有人能告诉我我做错了什么吗?我花了整整一天来排除故障,但我无处可去......我想将事件“onmouseover”添加到我的span元素中。但是当我实现下面的代码时,没有任何反应。我做了一些谷歌搜索,我认为这可能是一个变量范围的问题?我不太确定......感谢任何帮助!
<!DOCTYPE html>
<html>
<head>
<title>Fixing bugs in JS</title>
<script src="question1.js" type="text/javascript"></script>
<head>
<body>
<div id="output"></div>
</body>
<html>
var NUMBERS = 100;
function go()
{
var out = document.getElementById("output");
for (var i = 1; i < NUMBERS+1; i++) {
var span_one = document.createElement("span");
span_one.id = "span" + i;
span_one.innerHTML = "" + i;
out.appendChild(span_one);
if (isPrime(i) === true) { // where i is a prime number (3, 5, 7..etc)
span_one.style.backgroundColor = "red";
span_one.onmouseover = function() {
hover("span"+i, "yellow", "150%")
};
span_one.onmouseout = function() {
hover("span"+i, "red", "100%") // whatever color in this line always overrides previous set color...
};
}
function hover(id, color, size) {
var span = document.getElementById(id);
span.style.backgroundColor = color;
span.style.fontSize = size;
}
function etc() {
...
}
window.onload=go;
答案 0 :(得分:1)
实际上没有必要(a)给元素一个id(b)来使用i计数器来创建它们以外的任何东西。 这是另一种选择。
function newEl(tag){return document.createElement(tag)}
function byId(id){return document.getElementById(id)}
window.addEventListener('load', onDocLoaded, false);
function onDocLoaded(evt)
{
var i, n = 100;
var outputContainer = byId('output');
for (i=1; i<=n; i++)
{
var span = newEl('span');
//span.id = 'span_' + i;
span.textContent = i;
outputContainer.appendChild(span);
if ( i%2 == 1) // isOdd
{
span.addEventListener('mouseover', onSpanMouseOver, false);
span.addEventListener('mouseout', onSpanMouseOut, false);
}
}
}
function onSpanMouseOver(evt)
{
this.style.backgroundColor = 'yellow';
this.style.fontSize = '150%';
}
function onSpanMouseOut(evt)
{
this.style.backgroundColor = 'red';
this.style.fontSize = '100%';
}
<div id='output'></div>
答案 1 :(得分:0)
这是一个有效的例子:
http://jsbin.com/zixeno/edit?js,console,output
问题正是enhzflep所说的。一种解决方案是将“addSpan”逻辑移出for循环并进入函数。
var NUMBERS = 100;
function go() {
var out = document.getElementById("output");
for (var i = 1; i < NUMBERS+1; i++) {
addSpan(i);
}
function hover(id, color, size) {
var span = document.getElementById(id);
span.style.backgroundColor = color;
span.style.fontSize = size;
}
function addSpan(i) {
var span_one = document.createElement("span");
span_one.id = "span" + i;
span_one.innerHTML = "" + i;
out.appendChild(span_one);
if (isPrime(i) === true) {
span_one.style.backgroundColor = "red";
span_one.onmouseover = function() {
hover("span"+i, "yellow", "150%")
};
span_one.onmouseout = function() {
hover("span"+i, "red", "100%");
};
}
}
}
答案 2 :(得分:0)
问题在于变量-Dsonar.analysis.mode=
,它是闭包的常见问题。有关详细信息,请查看Simplify
并转到i
部分。要解决此问题,请将Creating closures in loops: A common mistake
for for循环更改为var
。这将有助于您保留范围,从而解决问题。
let
var NUMBERS = 100;
function go() {
var out = document.getElementById("output");
for (let i = 1; i < NUMBERS+1; i++) {
let span_one = document.createElement("span");
span_one.id = "span" + i;
span_one.innerHTML = "" + i;
out.appendChild(span_one);
if (isPrime(i) === true) { // if a number is a prime then run this func
span_one.style.backgroundColor = "red";
span_one.onmouseover = function() {
hover("span"+i, "yellow", "150%")
};
span_one.onmouseout = function() {
hover("span"+i, "red", "100%") // whatever color in this line always overrides previous set color...
};
}
function hover(id, color, size) {
var span = document.getElementById(id);
span.style.backgroundColor = color;
span.style.fontSize = size;
}
//Added my custom function as it was not provided
function isPrime(i){
return i%2 != 0;
}
}
}
window.onload = go;
答案 3 :(得分:0)
您的问题是您的
i
变量周围有闭包。
只要将函数嵌套在另一个函数中,就会发生闭包。 代码运行不可预测的地方是嵌套函数使用祖先函数中的变量,而嵌套函数的寿命比相关祖先的寿命长。
此处,您的mouseover
和mouseout
函数依赖于父函数i
中的go
。由于mouseover
和mouseout
函数被附加到DOM元素,并且那些DOM元素将在页面被卸载之前保留在内存中,因此这些函数的生命周期将长于go
。这意味着i
声明的go
变量在go
完成时不会超出范围,并且两个鼠标函数将共享{{1}的相同值}。人类出现并移动鼠标时i
所具有的值是循环结束时的最后一个值。
一开始闭包可能很有挑战性,但您可以阅读更多关于它们here的内容。
在循环上将i
更改为var i
解决了这个问题,因为let i
为循环的每次迭代引入了块范围。
另外,我看到你错过了两个导致错误的大括号。我添加了自己的let
函数。查看地点评论:
isPrime()
&#13;
window.onload=go;
const NUMBERS = 100;
function go(){
var out = document.getElementById("output");
// Using let instead of var avoids a closure by making sure
// that each looping number exists in the block scope of the
// loop and upon each iteration a new variable is created.
for (let i = 1; i < NUMBERS+1; i++) {
var span = document.createElement("span");
span.id = "span" + i;
span.innerHTML = i + "<br>";
out.appendChild(span);
if (isPrime(i)) { // where i is a prime number (2, 3, 5, 7..etc)
span.style.backgroundColor = "red";
// If you use the i variable in nested functions, you will create a
// closure around it and both the mouseover and mouseout functions will
// share the last known value of i. Each function must get its own copy
// of i.
span.onmouseover = function() {
hover("span" + i, "yellow", "150%")
};
span.onmouseout = function() {
// whatever color in this line always overrides previous set color...
hover("span" + i, "red", "100%")
};
} // <-- Missing
} // <-- Missing
}
function isPrime(value) {
for(var i = 2; i < value; i++) {
if(value % i === 0) {
return false;
}
}
return value > 1;
}
function hover(id, color, size) {
var span = document.getElementById(id);
span.style.backgroundColor = color;
span.style.fontSize = size;
console.log(id, span);
}
&#13;