资讯专栏INFORMATION COLUMN

关于setTimeout 第一个参数的问题解析

ghnor / 2314人阅读

摘要:总之,在的时候尽量不要用字符串的参数,因为具有许多不可预见的危险性,比如说可能有意外的运行结果可能隐式创建全局变量,闭包作用域解析过多消耗,,运行慢啊巴拉巴拉之类的。但是我们也需要了解下的一些黑魔法,以防到时候懵逼。

题目为什么叫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的一些黑魔法,以防到时候懵逼。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/86890.html

相关文章

  • 关于javascript 中高级定时器若干问题

    摘要:闭包闭包是指有权访问另一个函数作用域中的变量的函数当某个函数被调用时,会创建一个执行环境及相应的作用域链。要注意通过第句声明的这个方法属于构造函数生成的对象,而不属于构造函数的变量对象,也就是说,并不存在于作用域链中。 看到评论里有仁兄建议我试试箭头函数,真是受宠若惊,本来写这篇文章也只是想记录写要点给自己日后看的。今天早上看到一篇总结javascript中this的文章JavaScr...

    zr_hebo 评论0 收藏0
  • 前端校招准备系列--js中setTimeout到底是什么?

    摘要:浏览器是多进程的,而浏览器的内核渲染进程是多线程的。如果已经将回调函数放进任务队列,但是主线程正在执行一个非常耗时的任务,当这个任务执行完毕后,主线程去任务队列中取任务,这个时候,就会出现连续执行的情况,也就是说相当于失效了。 前言   在刷笔试题的时候,经常会碰到setTimeout的问题,只知道这个是设置定时器;但是考察的重点一般是在一个方法中包含了定时器,定时器中的打印和方法中打...

    Godtoy 评论0 收藏0
  • 在编写javascript时要注意一些细节

    摘要:不单单是因为引起的。用与要注意的地方这里要注意的是这二个函数的第一个参数都会把指向还有第一个参数可以为但不要这样用因为这样等于自己隐式使用了。 自动分号插入 Js不像其他语言强制要求;号结尾不然编译不过,原因是JS有自动;号的插入。 var text=function(){} text() 这样你不加;号也能运行其实在内部js是需要;号去帮助解析的 var text=function(...

    Eric 评论0 收藏0
  • 关于 ES6 中 Promise 面试题

    摘要:执行,输出,宏任务执行结束。到此为止,第一轮事件循环结束。参考入门阮一峰系列之我们来聊聊一道关于应用的面试题阿里前端测试题关于中函数的理解与应用这一次,彻底弄懂执行机制一个面试题原生的所有方法介绍附一道应用场景题目异步流程控制 说明 最近在复习 Promise 的知识,所以就做了一些题,这里挑出几道题,大家一起看看吧。 题目一 const promise = new Promise((...

    dreambei 评论0 收藏0
  • 关于Promise

    摘要:是一种异步编程的解决方案相比传统回调函数更合理立即执行性立即执行返回成功后执行控制台输出立即执行后执行返回成功对象表示未来发生的事件在创建时作为参数传入的函数是会被立即执行的只是其中执行的代码可以是异步代码有些人会认为当对象调用方法时接受的 Promise是一种异步编程的解决方案,相比传统回调函数更合理. 1.Promise立即执行性 let p = new Promise((reso...

    stdying 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<