A strange phenomenon that occurs when using setTimeout (fn, 0)

  1. Code

html

setTimeout

<p id="one"> <input type="text" id="input" value=""> <span></span>

setTimeout

<p id="second"> <input type="text" id="input" value=""> <span></span>

js

document.querySelector("-sharpone input").onkeydown = function() {
    document.querySelector("-sharpone span").innerHTML = this.value;
}
document.querySelector("-sharpsecond input").onkeydown = function() {
    setTimeout(function() {
        document.querySelector("-sharpsecond span").innerHTML = document.querySelector("-sharpsecond input").value;
    }, 0);
}

phenomenon

clipboard.png

Feb.27,2021

onkeydown is triggered when the user presses the keyboard key, followed by changing the value of input, and then triggering onkeyup.
so in the first case, in the callback function, the span element sets the unchanged value of input. In the second case, setTimeout puts the operation of modifying the span element after the Synchronize event, and the value of input has changed.
if you want to achieve the same effect, you can use onkeyup instead.
demo


it doesn't really have much to do with setTimeout, it's about onkeydown events.

first of all, you need to understand this event

The

onkeydown property triggers the
onkeypress event when the user presses a key (on the keyboard), which occurs when the keyboard key is pressed and a key is released. The
onkeyup event occurs when the keyboard key is released.

when the user presses the key for the first time, the value is actually empty. You can print this.value; in the onkeydown event


keydown replace it with keyup ,

reason: keydown -> value change-> keyup (if there is no keyup beyond a certain interval, it will continue keydown ), setTimeout with a minimum interval, resulting in capturing the changed value. When there is no setTimeout , the value is captured directly, and the test stamp demo <


to put it colloquially,
what you type is not immediately assigned to this.value, it has a stack order.
but after using setTimeout (fn, 0), the fn code will be placed at the end of the execution stack to be executed.


first of all, the delay is set to 0, which is not really delay-free; second, the execution of setTimeout will be joined in a separate queue, and tasks in this queue will not be executed


when the main queue is not finished.

setTimeout when the delay is set to 0, the current operation is placed at the end of the event queue to be executed, because the last event in the event queue is actually a click event, so the content in setTimeout is executed only after the click event is completed.

and during the execution of the click event, the listening event is after the keydown execution, and then the input box is assigned a value. The click's subsequent events include keyup , keyup event execution, and then the click event is completed before the stack is released from the event queue.


document.querySelector('-sharpone input').onkeydown = function() {
        alert('one');
        document.querySelector('-sharpone span').innerHTML = this.value;
    }
    document.querySelector('-sharpsecond input').onkeydown = function() {
        alert('second1');
        setTimeout(function() {
            alert('second2');
            document.querySelector('-sharpsecond span').innerHTML = document.querySelector('-sharpsecond input').value;
        }, 0);
    }

add an alert breakpoint in the middle to know
1.input when the keyboard is pressed, onkeydown executes first, then has a value, and cannot get the last input value
2.input when the keyboard is pressed, onkeydown is also executed first, and then triggers an asynchronous setTimeout, value and then executes asynchronous setTimeout, so the last input value can be obtained.

It can be solved by changing

onkeydown to onkeyup. Because onkeyup is triggered when the key is released, the onkeyup will be executed first with a value.

Menu