为什么window.setTimeOut(somefunc,0)与直接调用某些func



我正在尝试使用网页中的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基本上以0的延迟调用mclose。我认为mclosetime是一个函数,它无能为力并且可以删除。因此,我将其删除并更改了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引起的,所以我更改了mclose

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

仍然发生了同样的事情。

我真的很困惑。如果超时为0,window.setTimeout不只是调用该函数?如果没有做任何事情,请在此处致电mclose

setTimeout(myFun, 0)不能直接被称为myFun

在挂钩下,当您执行window.setTimeout(myFun, 0)时,浏览器将功能myFun放在浏览器事件队列中。并且浏览器只有在队列中没有其他内容时立即执行它。因此,队列中是否存在某些东西,它将比您的myFun更早执行。

setTimout的工作异步。这意味着,一旦当前呼叫堆栈完成执行,它将排队mclose。如果您直接调用mclose,它将在当前呼叫堆栈中按顺序执行(同步),但setTimout在下一个呼叫堆栈中立即执行它。

您的 settimeout 函数没有问题。问题在于JavaScript的mouse-out事件,也将其应用于嵌套的子元素。一旦将鼠标移到儿童div时,就会发射父母的鼠标事件。 jQuery 通过使用其mouseleave事件为您想要的,为此问题提供了一个简单的解决方案。

https://api.jquery.com/mouseleave/

最新更新