冷知识,Chrome 控制台console.log()为什么返回undefined

2,758 阅读3分钟

我正在参加「掘金·启航计划」

前言

不知道各位有没有在Chrome控制台中,使用console.log()输出数据,例如

console.log('Hello World')

image-20230221162917399

如果你曾经稍微留意,你会发现第二个返回值是undefined。是浏览器控制台出现BUG了嘛?我们期望的输出只有'Hello World'。

其实这是因为Chrome Console 是一个 REPL 环境导致的,

REPL

读取-求值-输出”循环(英语:Read-Eval-Print Loop,简称REPL),也被称做交互式顶层构件(英语:interactive toplevel),是一个简单的,交互式的编程环境。这个词常常用于指代一个Lisp的交互式开发环境,也能指代命令行的模式。

也就是说REPL环境的交互模式是:

  1. 接收你的输入,
  2. 然后运行,
  3. 输出结果,
  4. 继续接收你的输入。

你可以用下面的表达式来描述这种交互模式:

(loop (print (eval (read))))

所以最简单的理解【Chrome 控制台console.log()为什么返回undefined】就是:

当你在Chrome Console输入代码回车后,然后把这段代码作为字符串参数传给 eval 函数然后执行。eval 函数返回字符串代码的返回值。如果返回值为空,则返回 [undefined]。

探究

上面我们简单的说明了输出undefined的原因,现在我们再来仔细的了解!

普通声明

看下面这个例子:

image-20230221164922316

我们给变量进行了复制的操作,返回的结果同样也是undefined。现在我们用REPL来解释:

  1. 控制台读取了var name = "半夏";

  2. 把它作为字符串传递给了eval()函数去执行:

    string = 'var name = "半夏";'
    eval(string)
    
  3. 因为我们只是声明了一个变量,没有任何返回值,所以eval()执行完成之后打印了undefined

无return函数

下面我们来看一个函数的例子:

image-20230221170038544

各位此时应该在想,因为函数都是有返回值的,如果没有显式的return,那么默认的返回值就是undefiend,所以这里输出undefiend真的是这样子的嘛???

有return函数

那再来看看下面这个例子:

image-20230222085829441

我明明给函数增加了返回值,但是为啥还是返回的undefiend,道理其实很简单! 我们在这里其实还只是声明了一个函数,跟第一个例子的效果是一致的。

当我们执行该函数的时候,此时的执行才给出了返回值。

image-20230222085921670

总结

综合上面三个例子,我们是不是对Chrome 控制台执行console.log()为啥输出undefined做出解释!

console.log()本身并不返回任何值,在Chrome中,console.log() 是由开发工具的 Console 面板实现的。当代码中调用 console.log() 时,实际上是将输出内容传递给了 Console 面板,由它来负责显示。所以当我们在控制台使用console.log()时,它只是简单地将我们指定的信息打印到控制台上,而不会返回任何实际的值。因此,console.log()返回undefined是因为它本身没有返回值。

附录

Chrome 的 V8 引擎中,console.log() 被封装成一个 C++ 函数,该函数会将传入的参数转换为字符串并打印到控制台上。

然后,在 ChromeDevTools 中,console.log() 被再次封装成一个 JavaScript 函数,该函数会对传入的参数进行处理,并将其渲染到控制台上。

具体地说,这个 JavaScript 函数会先对传入的参数进行格式化,将其转换为一个可显示的对象。如果传入的参数是一个对象,会对其进行序列化并添加到一个消息队列中;如果传入的参数是一个字符串,会将其包装成一个包含该字符串的对象并添加到消息队列中。然后,这个 JavaScript 函数会将消息队列中的内容进行渲染,并在控制台上显示出来。