javascript - 为什么 window.setTimeout(someFunc, 0) 和直接调用 someFunc 不一样?

标签 javascript drop-down-menu

我正在尝试在我的网页中使用 JS 实现下拉菜单。我知道这可以通过 CSS 实现,但我仍然想使用 JS 来实现。

所以我在 Google 上四处搜索并找到了这段代码:

var timeout         = 500;
var closetimer      = 0;
var ddmenuitem      = 0;

// open hidden layer
function mopen(id)
{   
    // cancel close timer
    mcancelclosetime();

    // close old layer
    if(ddmenuitem) ddmenuitem.style.visibility = 'hidden';

    // get new layer and show it
    ddmenuitem = document.getElementById(id);
    ddmenuitem.style.visibility = 'visible';

}
// close showed layer
function mclose()
{
    if(ddmenuitem) ddmenuitem.style.visibility = 'hidden';
}

function mclosetime()
{
    closetimer = window.setTimeout(mclose, timeout);
}

// cancel close timer
function mcancelclosetime()
{
    if(closetimer)
    {
        window.clearTimeout(closetimer);
        closetimer = null;
    }
}

// close layer when click-out
document.onclick = mclose; 
#sddm
{   margin: 0;
    padding: 0;
    z-index: 30}

#sddm li
{   margin: 0;
    padding: 0;
    list-style: none;
    float: left;
    font: bold 11px arial}

#sddm li a
{   display: block;
    margin: 0 1px 0 0;
    padding: 4px 10px;
    width: 60px;
    background: #5970B2;
    color: #FFF;
    text-align: center;
    text-decoration: none}

#sddm li a:hover
{   background: #49A3FF}

#sddm div
{   position: absolute;
    visibility: hidden;
    margin: 0;
    padding: 0;
    background: #EAEBD8;
    border: 1px solid #5970B2}

    #sddm div a
    {   position: relative;
        display: block;
        margin: 0;
        padding: 5px 10px;
        width: auto;
        white-space: nowrap;
        text-align: left;
        text-decoration: none;
        background: #EAEBD8;
        color: #2875DE;
        font: 11px arial}

    #sddm div a:hover
    {   background: #49A3FF;
        color: #FFF}
<ul id="sddm">
    <li><a href="#" onmouseover="mopen('m1')" onmouseout="mclosetime()">Home</a>
        <div id="m1" onmouseover="mcancelclosetime()" onmouseout="mclosetime()">
        <a href="#">HTML DropDown</a>
        <a href="#">DHTML DropDown menu</a>
        <a href="#">JavaScript DropDown</a>
        <a href="#">DropDown Menu</a>
        <a href="#">CSS DropDown</a>
        </div>
    </li>
    <li><a href="#" onmouseover="mopen('m2')" onmouseout="mclosetime()">Download</a>
        <div id="m2" onmouseover="mcancelclosetime()" onmouseout="mclosetime()">
        <a href="#">ASP Dropdown</a>
        <a href="#">Pulldown menu</a>
        <a href="#">AJAX dropdown</a>
        <a href="#">DIV dropdown</a>
        </div>
    </li>
    <li><a href="#" onmouseover="mopen('m3')" onmouseout="mclosetime()">Order</a>
        <div id="m3" onmouseover="mcancelclosetime()" onmouseout="mclosetime()">
        <a href="#">Visa Credit Card</a>
        <a href="#">Paypal</a>
        </div>
    </li>
    <li><a href="#" onmouseover="mopen('m4')" onmouseout="mclosetime()">Help</a>
        <div id="m4" onmouseover="mcancelclosetime()" onmouseout="mclosetime()">
        <a href="#">Download Help File</a>
        <a href="#">Read online</a>
        </div>
    </li>
    <li><a href="#" onmouseover="mopen('m5')" onmouseout="mclosetime()">Contact</a>
        <div id="m5" onmouseover="mcancelclosetime()" onmouseout="mclosetime()">
        <a href="#">E-mail</a>
        <a href="#">Submit Request Form</a>
        <a href="#">Call Center</a>
        </div>
    </li>
</ul>
<div style="clear:both"></div>

<div style="clear:both"></div>

我对 JS 进行了一些编辑,因为我希望在鼠标指针移出下拉菜单后下拉菜单立即消失。所以我把它改成这样:

function mclosetime()
{
    closetimer = window.setTimeout(mclose, 0);
}

并删除了 timeout 变量。一切仍然有效。然后我意识到mclosetime基本上调用了mclose,延迟为0。 .所以我删除了它并将 li 元素更改为直接调用 mclose:

    <li><a href="#" onmouseover="mopen('m1')" onmouseout="mclose()">Home</a>
        <div id="m1" onmouseover="mcancelclosetime()" onmouseout="mclose()">
        <a href="#">HTML DropDown</a>
        <a href="#">DHTML DropDown menu</a>
        <a href="#">JavaScript DropDown</a>
        <a href="#">DropDown Menu</a>
        <a href="#">CSS DropDown</a>
        </div>
    </li>

然后下拉菜单不再起作用了!当我将鼠标指针移动到下拉菜单时,下拉菜单就会消失。我认为这是由于 closetimer 为 0 造成的,所以我将 mclose 更改为:

function mclose()
{
    closetimer = 1;
    if(ddmenuitem) ddmenuitem.style.visibility = 'hidden';
}

仍然发生同样的事情。

我真的很困惑。如果超时为 0,window.setTimeout 是否只调用该函数?如果它没有做更多的事情,那么在这里调用 mclose 应该可以!

最佳答案

setTimeout(myFun, 0) 不能保证 myFun 会立即被调用。

在 Hook 下,当您执行 window.setTimeout(myFun, 0) 时,浏览器只是将函数 myFun 放入浏览器事件队列。只有当队列中没有其他内容时,浏览器才会立即执行它。那么队列中是否存在某些东西,它会比你的 myFun 更早执行。

关于javascript - 为什么 window.setTimeout(someFunc, 0) 和直接调用 someFunc 不一样?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42606549/

相关文章:

android - 下拉项的 AutoCompleteTextView 边距

javascript - 每次发送请求时检索轮询 URL - Socket.io

javascript - 允许空格的表达式的正则表达式最小值最大值

javascript - 使用无状态函数定义组件时如何初始化状态

javascript - 我可以获得具有多种状态的 Stripe 订阅列表吗?

css - 2 级 CSS 下拉菜单 - 显示 : none Does not Work

javascript - 如何创建一个巨大的复选框表(我的意思是巨大!)

c# - 在下拉列表控件中以编程方式设置默认文本

css - 下拉宽度与父级相同

html - 使用纯 CSS 创建点击多级下拉菜单