setTimeout的妙用

定义和用法

setTimeout() 方法用于在指定的毫秒数后调用函数或计算表达式。

基本用法

下面的代码将在"大约"2s后输出s;为什么是大约呢?因为并不能保证准确的2s后执行,因为js是单线程,setTimeout只是在2s后插入任务队列。

//两个参数 1.要执行的函数表达式 2.延迟时长(单位毫秒)
setTimeout("console.log('s')",2000);

第一个参数为函数

例如下面

function a(s){
console.log(s);
}
setTimeout("a('dd')",1000);
//dd

注意:如果参数不是全局变量要传递参数时

function a(s){
console.log(s);
}
function b(){
var c="ss";
}
setTimeout(function(){a(c);},1000);

任务队列

以下代码会怎么执行呢?

setTimeout("console.log('s')",0);
for(var i=0;i<100;i++){
console.log(i);
}

答案是先输出0-99,然后输出s。这就是为什么setTimeout不能保证按时执行的原因,因为其他代码执行“优先级”更高。

其他用法

一.

以下一段简单的代码,在线演示地址http://jsrun.net/7piKp/edit
html

<input type="" name="" onkeydown="set(event)">
<p id="show"></p>

script

function set(e) {
        var show = document.querySelector("#show");
        show.innerText = e.target.value;
}

结果

同步

我们发现结果总是慢半拍,这时因为当我们按下按钮时input里面的value值还没来得及改变我们就获取他,导致值的获取慢一步。
所以我们可以稍微“延后”一下值的获取。在线地址http://jsrun.net/cpiKp/edit

function set(e) {
        var show = document.querySelector("#show");
        setTimeout(show.innerText = e.target.value, 0);
}

结果就和我们想的一样了。当然直接把onkeydown换成onkeyup就不需要使用setTimeout了。
二.
这次是在动画中使用,当我们做元素进入动画的时候
html

<div class="s"></div>
<button onclick="set()">添加动画</button>

css

.s {
        width: 200px;
        height: 200px;
        background: red;
    }

js

function set() {
        var ele = document.querySelector(".s");
        ele.style.transition = "none";
        ele.style.transform = "translateX(200px)";
        ele.style.transition = "all 1s ease-in";
        ele.style.transform = "translateX(0)";
}

我们点击按钮后先后为div添加了两个transform,我们期望的效果是div从200缓慢移动到0,但结果就是这两个transform相互抵消了,这也是浏览器渲染优化的一部分。
但是我就是想做这种动画怎么办?当然可以,仿照上面,既然浏览器会把两个transform抵消那我们就稍微“延后”一下,在线演示地址http://jsrun.net/FpiKp/edit

    function set() {
        var ele = document.querySelector(".s");
        ele.style.transition = "none";
        ele.style.transform = "translateX(200px)";
        //ele.offsetWidth;
        setTimeout(function() {
            ele.style.transition = "all 1s ease-in";
            ele.style.transform = "translateX(0)";
        }, 0);
    }

当然不使用setTimeout也是可以的,使用ele.offsetWidth或者ele.offsetHeight来触发重绘也是可以的。

推荐阅读更多精彩内容