2016-11-27 172 views
0

有人能告诉我我做错了什么吗?我花了整整一天的时间解决这个问题,但我无处可去......我想将事件“onmouseover”添加到我的span元素中。但是,当我执行下面的代码时,没有任何反应。我做了一些谷歌搜索,我认为这可能是一个变量范围问题?我不太确定...任何帮助表示赞赏!添加事件“onmouseover”时遇到问题

<!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

的问题是,调用时,'i'不再持有它所需要持有。 (我在onmouseover中的值不同于当它用作isPrime的参数时) – enhzflep

+0

@enhzflep我通过console.log(span_one.id)进行了检查,它保存了它假设的值... – aeml

+0

这就是不是一回事。 'span_one.id' _应该保持与'i'相同的值,但它不会。 – enhzflep

回答

0

你的问题是,您对您的i变量关闭。

无论何时将函数嵌套在另一个函数中,都会发生闭包。 代码在不可预知的情况下运行时,嵌套函数使用来自祖先函数的变量,并且嵌套函数的寿命比有问题的祖先更长。

在这里,您的mouseovermouseout函数依赖于父函数goi。由于mouseovermouseout函数正在附加到DOM元素,并且这些DOM元素将保留在内存中直到页面被卸载,所以这些函数的寿命将比go长。这意味着当go完成时go声明的i变量不能超出范围,并且这两个鼠标函数将共享相同的值ii在人类出现并移动鼠标时的值是循环结束时的最后值。

首先关闭屏幕可能会很有挑战性,但您可以多阅读一些关于它们的文章here

在循环中更改var ilet i解决了这个问题,因为let为循环的每次迭代都引入了块范围。

此外,我看到你错过了两个导致错误的大括号。我添加了我自己的isPrime()函数。看评论的地点:

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); 
 
}
<div id="output"></div>

+0

嗨@斯科特马库斯,我怎么能打破这些数字,让每个人都有自己的线?当我添加out.innerHTML + =“
”;,它打破了代码。我不再获得onmouseover效果。 – aeml

+0

@aeml我已经更新了我的答案。你只需要改变:'span.textContent = i;'为这个:'span.innerHTML = i +“
”;' –

+0

非常感谢! – aeml

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%"); 
     }; 
    } 
    } 
} 
0

问题出在变量i,它是闭包的一个常见问题。欲了解更多信息,你可以看看MDN closures并转到部分Creating closures in loops: A common mistake。要解决这个问题,请将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;
<div id="output"></div>

+0

你的结果是OP想要的东西的逆转。素材应该是红色的。 –

1

真的没有必要(a)给予该元素的ID(B)使用我计数器超过创建它们的环路的任何其他。 这是一个替代方案。

function newEl(tag){return document.createElement(tag)} 
 
function byId(id){return document.getElementById(id)} 
 

 
window.addEventListener('load', onDocLoaded, false); 
 

 
function onDocLoaded(evt) 
 
{ 
 
\t var i, n = 100; 
 
\t var outputContainer = byId('output'); 
 
\t 
 
\t for (i=1; i<=n; i++) 
 
\t { 
 
\t \t var span = newEl('span'); 
 
\t \t //span.id = 'span_' + i; 
 
\t \t span.textContent = i; 
 
\t \t outputContainer.appendChild(span); 
 
\t \t 
 
\t \t if (i%2 == 1) \t // \t isOdd 
 
\t \t { 
 
\t \t \t span.addEventListener('mouseover', onSpanMouseOver, false); 
 
\t \t \t span.addEventListener('mouseout', onSpanMouseOut, false); 
 
\t \t } 
 
\t } 
 
} 
 

 
function onSpanMouseOver(evt) 
 
{ 
 
\t this.style.backgroundColor = 'yellow'; 
 
\t this.style.fontSize = '150%'; 
 
} 
 
function onSpanMouseOut(evt) 
 
{ 
 
\t this.style.backgroundColor = 'red'; 
 
\t this.style.fontSize = '100%'; 
 
}
<div id='output'></div>

+0

您的代码不会对代码着色。 –

+0

@ScottMarcus - 废话。演示在这里的页面中工作。发帖之前没有尝试过吗? (我这样做)奇数在盘旋时变成黄色,当鼠标离开时变成红色。 – enhzflep

+0

素数应自动变红。然后,当它们被淹没时,它们会变黄,然后在褪色时变回红色。 –