在js的开发过程中,我们不可避免的需要对某些参数的状态进行追踪,这个时候就回使用console.log这个函数,但这个简单函数背后你所不知道的一面

这个函数最常规的使用方式就是在代码的任何部分调用console.log,然后可以在浏览器的开发者控制台里,看到这个函数调用的那一瞬间你指定的变量或表达式的值,可事实真的是这样吗?眼见真的为实吗?

打印信息是同步的?

我们来看看这段代码,应该不难猜测运行之后的结果吧?

    testConsole() {
      let yerik = {
        shu: 1,
      };
      console.log(yerik);
      yerik.NAUG = 111;
      console.log(yerik);
    },

运行结果1.png

这个方式就是我们常见的一种变量追踪手法,我愿称之为"面向print"开发

从这个例子来看似乎没什么问题,那么我们让这个变量变得更加复杂一些

    testConsole() {
      let yerik = {
        shu: { s: 1, h: 2, u: 0, n: 0, a: 1, U: 2, g: 3 },
      };
      console.log(yerik);
      yerik.NAUG = 111;
      console.log(yerik);
    },

我们将shu这个属性从原来的整型变成object之后,再用console打开,欸,奇怪了,讲道理应该是不会在第一行就显示带有NAUG这个属性的啊,为什么在控制台上面存在呢?

运行结果2.png

眼见真不为实

进一步分析

in

判断对象里面有没有这个属性,最好的方式就是遍历一遍属性,有就是有,没有就是没有

    testConsole() {
      let yerik = {
        shu: { s: 1, h: 2, u: 0, n: 0, a: 1, U: 2, g: 3 },
      };
      console.log(yerik);
      Object.keys(yerik).forEach((item) => console.log(item));
      console.log("NAUG" in yerik);
      yerik.NAUG = 111;
      console.log(yerik);
      console.log("NAUG" in yerik);
    },

运行结果3.png

这么一看还真没呀,嗷,这个是写代码写多了,瞎了吗!!!!那个圈圈里面的属性不是写的明明白白吗!?!?

观察到!

两次的实验下来,突然发现有个感叹号logo,可能是翻译的原因,读起来很拗口,不过有个关键字倒是让人很兴奋,"已更改",那么我们接下来就是寻找已更改的原因了

运行结果4.png

联想到“提升”

依稀记得在学习的过程中,接触过作用域,这玩意说简单点就是你的程序存放变量、变量值和函数的地方。根据作用范围不同可以分为全局作用域和局部作用域,这次遇到的问题是在各自的作用域内,声明和赋值的位置是不是在执行的过程中被“优化”过?我们看看以下这段代码,观察下作用域的工作过程

    workspace() {
      console.log(study);
      var study = "神奇js引擎";
      function testSpace() {
        console.log(study);
        var study = "20210823";
        console.log(study);
      }
      testSpace();
      console.log(study);
    },

运行结果5.png

在这里我们看到了有两个undefined意味着什么呢?未赋值,虽然显示的是未定义,但实际上已经定义了,不然不可能出现对应的回显。这个执行的过程的代码实际上是这样的?

var study
console.log(study)
study = "20210823"

我们习惯将var study="20210823";看做是一个声明,而实际上javascript引擎并不这么认为。它将var study和study = "20210823"看做是两个单独的声明,第一个是编译阶段的任务,而第二个则是执行阶段的任务。

基于这个分析,我们再回过头来看下原来的代码,我们虽然是在代码中间进行赋值,但是由于“作用域提升”的存在,导致我们看到了这个NAUG的存在

运行结果6.png

接下来我们还需要解决为何通过遍历或者检索都没有发现对应NAUG的存在这个问题。

事实上,在stackoverflow上面,有个老哥回答了这个问题,我的理解是这个NAUG本来是不存在的,但是当我们点开这个对象的时候,会被再渲染一次,毕竟log都只打当前状态,不是代码当时的状态,从而出现了我们观察到的现象

各位你们的看法是怎样的呢?:)

参考资料

  1. https://developer.mozilla.org/zh-CN/docs/Web/API/Console/log
  2. https://nodejs.org/docs/latest/api/console.html#console_console_log_data
  3. https://stackoverflow.com/questions/17546953/cant-access-object-property-even-though-it-shows-up-in-a-console-log