簡體   English   中英

無法在setTimeout中設置innerHTML

[英]Cannot set innerHTML inside setTimeout

試圖設置一個HTML類的innerHTML,它們是四個盒子,每個盒子一個接一個地設置3秒。 當innerHTML設置為加載圖標時,我可以在不使用setTimeout的情況下設置innerHTML。 當innerHTML放在setTimeout中時,返回以下內容:'Uncaught TypeError:無法設置undefined'的屬性'innerHTML'。

試圖調試我的代碼發送消息到控制台和搜索stackoverflow但沒有運氣。

var x = document.getElementsByClassName("numberBox");


for (var i = 0; i < 4; i++) {
    x[i].innerHTML= '';
    x[i].innerHTML= "<div class='loader'></div>"
}

// function to generate array of 4 random numbers
var randomNums = generateRandomNumbers();


for (var i = 0; i < 4; i++) {
    setTimeout(function () {
        x[i].innerHTML= '';
        x[i].innerHTML = randomNums[i];
    }, 3000 * i);
}

想知道為什么我的innerHTML不能在setTimeout中設置這里以及我的問題的可能解決方案。

我認為這是目前范圍的問題。 setTimeout函數創建自己的范圍,該范圍沒有引用舊變量。 您可能需要重新定義超時內的x或將數組顯式傳遞給超時。

請參閱此處了解操作方法: 如何將參數傳遞給setTimeout()回調?

我還建議你閱讀關閉器: https//developer.mozilla.org/en-US/docs/Web/JavaScript/Closures

當您使用var for循環里面setTimeout實際上是觸發的最后一個值ivar綁定只發生一次。

這是因為當整個循環完成時會觸發setTimeout ,然后你的i將為4 請記住,由於您在setTimeout調用中傳遞的回調函數,因此存在閉包。 那個閉包現在將指的是i的最終值為4。

所以在這種情況下,當完成循環執行時, i值為4但x中的索引最多為3 這就是為什么當你嘗試訪問x[4]你會得到undefined ,你會看到TypeError來解決這個問題,只需使用let在每次迭代中重新綁定i的新值:

for (let i = 0; i < 4; i++) {
    setTimeout(function () {
        x[i].innerHTML= '';
        x[i].innerHTML = randomNums[i];
    }, 3000 * i);
}

此外,如果由於瀏覽器不兼容而無法使用let ,您可以使用IIFE執行此操作:

for (var i = 0; i < 4; i++) {
      (function(i){
         setTimeout(function () {
           x[i].innerHTML= '';
           x[i].innerHTML = randomNums[i];
         }, 3000 * i);
       })(i);
 }

這是因為var具有函數作用域,因此在每次迭代中都會創建一個新的作用域以及具有對i的新值的新綁定的函數。

由於缺少i參數 - 超時可能使用last(4),這是在數組之外。

但您可以通過添加下一個超時參數來設置和使用函數參數。

 var x = document.getElementsByClassName("numberBox"); for (var i = 0; i < 4; i++) { x[i].innerHTML= ''; x[i].innerHTML= "<div class='loader'></div>" } // function to generate array of 4 random numbers var randomNums = generateRandomNumbers(); for (var i = 0; i < 4; i++) { setTimeout(function (i) { x[i].innerHTML= ''; x[i].innerHTML = randomNums[i]; }, 3000 * i, i); } function generateRandomNumbers() { var retVal = []; for (var i = 0; i < 4; i++) { retVal.push(Math.random()); } return retVal; } 
 <div class="numberBox"></div> <div class="numberBox"></div> <div class="numberBox"></div> <div class="numberBox"></div> 

    // function to generate array of 4 random numbers
    var x = document.getElementsByClassName("numberBox");
    var randomNums = generateRandomNumbers();
    for (var i = 0; i < 4; i++) {
        setTimeout(function () {
            x[i].innerHTML= '';
            x[i].innerHTML = randomNums[i];
        }, 3000 * i, x);
    }

這個問題與一個非常基本和流行的Javascript概念有關,稱為閉包 它可以通過至少兩種方式解決:

  1. 使用let
var x = document.getElementsByClassName("numberBox");


for (let j = 0; j < 4; j++) {
    x[j].innerHTML= '';
    x[j].innerHTML= "<div class='loader'></div>"
}

// function to generate array of 4 random numbers
var randomNums = generateRandomNumbers();


for (let i = 0; i < 4; i++) {
    setTimeout(function () {
        x[i].innerHTML= '';
        x[i].innerHTML = randomNums[i];
    }, 3000 * i);
}
  1. 使用IIFE

var x = document.getElementsByClassName("numberBox");


for (var i = 0; i < 4; i++) {
    x[i].innerHTML= '';
    x[i].innerHTML= "<div class='loader'></div>"
}

// function to generate array of 4 random numbers
var randomNums = generateRandomNumbers();


for (var i = 0; i < 4; i++) {
    setTimeout((function (j) {
        x[j].innerHTML= '';
        x[j].innerHTML = randomNums[j];
    })(i), 3000 * i);
}

您正試圖在內部方法中訪問x ,即x未在setTimeout范圍內定義,這就是您接收該execption的原因

我建議你使用setInterval函數作為解決方案你的代碼:

var randomNums = generateRandomNumbers(); 

for (var i = 0; i < 4; i++) { 

      setTimeout(function () { 
         x[i].innerHTML= ''; 
         x[i].innerHTML = randomNums[i]; 
     }, 3000 * i); 
}

一個解決方法

var randomNums = generateRandomNumbers();
let i = 0;
let interval = setInterval(function() {
            if( i != 2){
                    x[i].innerHTML= ''; 
                x[i].innerHTML = randomNums[i];
                    i += 1;
            } else {
                    clearInterval(interval) ;
            }
}, 3000);

這個問題似乎是由幾個因素造成的。

  • setTimeout()范圍之外定義generateRandomNumbers()函數。
  • for循環中使用var定義。
function generateRandomNumbers() {
    return Math.floor(Math.random() * 999999) + 10000;
}

var x = document.getElementsByClassName("numberBox");

for (var i = 0; i < x.length; i++) {
    x[i].innerHTML= '';
    x[i].innerHTML= "<div class='loader'></div>"
}

for (let i = 0; i < x.length; i++) {
    setTimeout(function() {
      x[i].innerHTML= '';
      x[i].innerHTML = generateRandomNumbers();
    }, 3000 * i);
}

這是一個不同的實現,但這是一個小提琴

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM