JS: 一个小例子引发的思考

一个小例子引发的思考

emmmm……

最近在看一个开源库,看其中的栗子中发现了一段很有意思的代码。栗子简化一下是下面的这个样子的:

function a() { console.log('a'); setTimeout(b); }
function b() { console.log('b') }
function c() { console.log('c') };

a(c());

可能你觉得这没什么,不就几个简单的方法调用么,有什么复杂的?那么我们先来看一下在Chrome的控制台里面会输出什么?

可能的确如你所料,控制台依次输出了c、a、b(虽然有个不知道什么鬼的undefined,这个等下再说),那说明你对JS中函数的执行顺序有一定的了解。的确,前面声明了三个方法,a,b,c,然后加上括号使a成为语句执行。但是a(c())这种写法怪怪的,内部怎么执行的?还有这个输出怎么会有一个undefined(面试题埋坑啊)?

我同样也有这样的疑问,那么深究之前,先整理一下我们的疑问。

这段代码的输出是什么?a(c())这种写法是什么鬼?undefined是什么鬼?setTimeout不写时间参数会咋样?会有浏览器差异么?

那么我们一个个的来为我们疑问来寻找答案……

这段代码的输出是什么?为什么会有这样子的输出?

其实答案已经看到了,就是c、a、b。因为JS是单线程执行的,所以在执行a方法的过程中,先执行了()中的语句,也就是c()方法,所以顺序执行也就是c、a、b。

emmm……说了和没说一样,没关系往下看。

a(c())这种写法是什么鬼?

接着上个答案的来说。要明白a(c())这种写法是什么鬼?我们得先了解在JS中()是个什么作用?对于普通的语句,()直接执行。对于函数来说,JavaScript解释器会在默认的情况下把遇到的function关键字当作是函数声明语句(statement)来进行解释的。先来看下面的这几个栗子:

(111)   // 常量,当做语句处理。打印 111

(var a)  // 变量声明。 报错

(a = 1)  // 赋值语句,不要写';'。打印 1

function(){console.log('aa')}()  // 匿名函数,不是标准的函数声明语句。报错

(function(){console.log('aa')}())  // 立即执行函数。打印 aa

(function(){console.log('aa')})()  // 立即执行函数。打印 aa

所以其实大致的意思已经很明了。 通俗的来讲就是 因为c首先是一个很标准的函数语句,然后()又可以执行语句,所以a(c())的执行顺序就是先执行了c方法,然后继续执行a方法。如果换成下面的这种方式c就不会执行了:

a(c());   // c、a、b

a(c);   // a、b

a(function(){console.log('nini')}); // a、b

好像也没有那么绕……

undefined是什么鬼?

基本路子搞明白了,那么这个undefined是什么鬼?其实很简单,这是Chrome控制台的一种默认机制,对于执行语句来说,控制台会默认去拿上一行语句的输出。

a = 1;  // 打印 1

var a = 1; // 打印 undefined, 因为这是两行语句

(function(){return 1;})() // 打印 1

function a() {} a(); // 打印 undefined

function a() { return 11; } a(); // 打印 1

所以打印undefined的问题找到了,那么问题来了,node中会不会打印呢?尝试了一波儿发现,node中并不会打印,所以同样是V8引擎,但是控制台这一块儿还是有差距的。

setTimeout不写时间参数会咋样?

终于碰到了最喜欢的setTimeout方法。查阅一堆乱七八糟资料后,setTimeout不写时间参数的话,会由浏览器默认给加上延迟参数,具体多少各家浏览器都不一样。

emmm……无所谓了,那么 setTimeout(func,0) 和 setTimeout(func) 有什么区别么?

下面两张图是在控制台进行了4次的对比试验。

没有时间参数

时间参数为0

好像加上0的确会快一些。不过我们也知道,即使是0,setTimeout 的作用也只是加到当前执行的事件队列当中,而且在浏览器端每次执行也会有4ms的延迟。具体的可以看一看我的另一篇: 看了这么久JS,事件队列你真的懂吗?

关于浏览器的4ms的差异延迟,我们暂时不用在意。当我们需要遇到性能瓶颈时可以去研究一下,具体的方案的实现还都挺有意思的。

会有浏览器差异么?

有,不过控制台的输出影响不大。不必在意。

结尾

以上,基本上该思考的都思考了,不知道你看到这里,还有什么在思考的,倘若有的话,不妨说来听听。

猜你喜欢

转载自blog.csdn.net/u013707249/article/details/78961047