关于setTimeout 第一个参数的题目剖析

题目为何叫setTimeout的第一个参数而不是回调函数?假如你心中有稍有迷惑,也许应当看看下面的文章

我们一样平常运用setTimeout(),平常是将函数作为第一个参数,然则也有例外情况,先看以下代码:

function test() {

  var cl = function() {

    console.log(666)

  }

  setTimeout('cl()', 1500)

}

test()

将以上代码CV到chrome中的console,运转发明:

Uncaught ReferenceError: cl is not defined

没有定义cl函数,新鲜是并没有报Uncaught SyntaxError: Unexpected identifier如许的语法错误,查javascript MDN我们就会发明:

setTimeout许可讲一个字符串作为第一个参数,而且js内部将会挪用eval()函数用来动态实行一段字符串剧本,至于为何找不到cl函数,我们猜测是作用域题目,既然是eval动态实行,我们在字符串参数中输出当前this绑定的对象:

function test() {

  var cl = function() {

    console.log(666)

  }

  setTimeout('console.log(this);cl()', 1500)

}

test()

实行后发明:

本来this绑定window全局对象,这下邃晓了,eval()实行动态剧本的时刻,在全局作用域并没有找到我们定义在函数test内部的cl,所以会报错。

我们将cl定义移到外部:

ok了

————分割线————

var cl = function() {console.log(666)}

setTimeout(cl(), 1500)

常常看到有新人在社区上问这段代码为何没有耽误实行,只需注重这边的cl()是一个函数实行而不是函数定义,假如想耽误实行,我们须要通报一个函数地点,比方:

var cl = function() {console.log(666)}

setTimeout(cl, 1500)

或许直接return一个函数:

var cl = function() {

    return function() {

        console.log(666)

    }

}

setTimeout(cl(), 1500)

又或许参数处直接定义:

setTimeout(function() {console.log(666)}, 1500)

归根结柢照样搞清援用函数地点和实行函数的区分

————分割线————

以上划定规矩也一样适用于字符串参数,只是字符串参数中要加上()保证eval的时刻实行,不要到时刻只是eval了一个地点 =。=,比方如许:

var cl = function() {

    console.log(666)

  }

function test() {

  setTimeout('cl', 1500)

}

test()

实行一下,啥屁也没看到 = 。=

总之,在setTimeout的时刻只管不要用字符串的参数,由于eval()具有很多不可预感的危险性,比方说能够有不测的运转效果,能够隐式建立全局变量,闭包作用域剖析过量斲丧,xss,运转慢啊巴拉巴拉之类的。然则我们也须要了解下js的一些黑魔法,以防到时刻懵逼。

    原文作者:BenjaminShih
    原文地址: https://segmentfault.com/a/1190000008643378
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞