V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
abcbuzhiming
V2EX  ›  JavaScript

浏览器端的 console.log 是借助渲染引擎实现的吗?并不是真正的“打印命令行”?

  •  1
     
  •   abcbuzhiming · 2018-07-13 17:38:16 +08:00 · 5731 次点击
    这是一个创建于 2359 天前的主题,其中的信息可能已经有所发展或是发生改变。
    以前我一直以为,浏览器端的 console.log 是一个真的“同步输出命令行”。就和其它大部分语言一样,你给它什么值,它就立刻打印到屏幕上去。但是最近在开发中发现的一个 bug 引发的现象,让我产生了疑问:
    这个 bug 是这样的,从服务器拿到的数据。服务器端打印的结果,和浏览器端最终的结果不一样,哪怕在浏览器端拿到数据后立即 console.log 输出,发现值也是和服务端给的不一样,研究了半天发现是在渲染代码里无意中少写了=号导致数据被改变了。但是有一点:console.log 可是在渲染代码之前就执行了的,然而输出到控制台上的数据却依旧是被篡改后的。这种现象的唯一解释是控制台其实是归浏览器的渲染引擎管的,就和渲染 DOM 是一条线,在 js 代码本身没执行完之前,console.log 并不会真正的输出内容。请问各位是不是这样?
    26 条回复    2018-07-14 18:00:54 +08:00
    StephenW
        1
    StephenW  
       2018-07-13 17:42:39 +08:00
    不是
    marcong95
        2
    marcong95  
       2018-07-13 17:48:10 +08:00
    console.log 是异步的这个应该不假,我也遇到过类似情况
    invalidtoken
        3
    invalidtoken  
       2018-07-13 17:50:32 +08:00 via Android
    如果是对象的话,后面有个 i 图标,放上去会有 “ Value below was evaluated just now ” 这个提示
    KeepPro
        4
    KeepPro  
       2018-07-13 17:51:31 +08:00   ❤️ 1
    并不是。比如:
    a = 1
    console.log(a)
    a = 2
    console.log(a)
    你所遇到的情况,应该是你用 console.log 输出了一个 Object,
    在输出的时候,浏览器工具拿这个 Object 的引用去取值的。
    有点像函数调用时候的 值传递 还是 引用传递的 区别。
    grewer
        5
    grewer  
       2018-07-13 18:00:41 +08:00
    才发现,看来是新手
    pabupa
        6
    pabupa  
       2018-07-13 18:18:57 +08:00 via Android
    是异步的~
    yimity
        7
    yimity  
       2018-07-13 18:19:07 +08:00 via Android
    你应该打印的是 object
    cuzfinal
        8
    cuzfinal  
       2018-07-13 18:23:31 +08:00
    什么鬼?
    肯定是你代码写的有问题。
    meteor957
        9
    meteor957  
       2018-07-13 18:26:46 +08:00 via Android
    到底是不是异步啊,楼上的大佬意见都不统一吗
    gynantim
        10
    gynantim  
       2018-07-13 18:59:15 +08:00   ❤️ 3
    当然是同步的 你打印 console.log(JSON.stringify(……))试试
    ThomasChan
        11
    ThomasChan  
       2018-07-13 19:37:12 +08:00
    7 楼说的对,如果打印的是 array, object,打印的实际上是引用值
    codehz
        12
    codehz  
       2018-07-13 19:53:18 +08:00
    console.log 的参数肯定是同步求值的。但是求出来的值肯定是被异步读取的(所以引用对象的话,可能就会产生变化
    grantonzhuang
        13
    grantonzhuang  
       2018-07-13 19:58:45 +08:00 via Android
    我的猜想,浏览器本质上也是个 GUI 程序,有定时重新渲染的机制,传给 console.log 的是一个引用,刷新的时候会重新去获取引用引用的值
    CDL
        14
    CDL  
       2018-07-13 20:09:14 +08:00
    输出的 object 也是对象引用,完
    abcbuzhiming
        15
    abcbuzhiming  
    OP
       2018-07-13 21:56:40 +08:00
    @invalidtoken 是的,后面有“ Value below was evaluated just now ”

    @KeepPro 我很奇怪的是这是 js 独有的吗,在别的语言我没发现这个现象,输出时多少就是多少


    @codehz 我是头一次发现有语言是这么干的
    var AAA = {b:1};
    console.log(AAA);
    AAA.b=2;
    像这样的代码,打印的话难道不应该就是打印时的值吗,为啥会是引用的值
    AlisaDestiny
        16
    AlisaDestiny  
       2018-07-13 21:58:52 +08:00
    如果你知道浏览器的控制台可以输出图片那么你心里就有答案了。
    codehz
        17
    codehz  
       2018-07-13 22:03:13 +08:00
    @abcbuzhiming #15 因为 console.log 并不是给用户看的。。。
    所以要保证尽可能减少消耗。。一个 dom 对象要完整的输出出来(不算循环引用的部分),比重新渲染一个网页的消耗都要大(一般情况),比如你看看 document 对象的属性数量。。。
    更别说还有原型链上的一堆东西。。。
    abcbuzhiming
        18
    abcbuzhiming  
    OP
       2018-07-13 22:22:24 +08:00
    @AlisaDestiny 你的意思是说这确实是浏览器 DOM 渲染发生时间原理造成的?


    @codehz 这到底是 js 的特性还是浏览器特性,我还没来得及做试验,服务器的 NodeJS 也是这样的吗?那以后真得小心点,我接触过不少编程语言了,这个 console.log 的输出特性和绝大部分语言的控制台输出都不一样。我还没找到和它类似的
    codehz
        19
    codehz  
       2018-07-13 22:23:45 +08:00
    NodeJS 的 console.log 当然是即时输出的,
    airdge
        20
    airdge  
       2018-07-13 22:52:10 +08:00
    nodejs:全局的 console 对象的方法既不总是同步的(如浏览器中类似的 API ),也不总是异步的(如其他 Node.js 流)

    http://nodejs.cn/api//console.html
    autoxbc
        21
    autoxbc  
       2018-07-13 23:02:22 +08:00 via iPhone
    引用对象和其原型链形成了一个十分巨大的树形结构,没有办法简单对其做快照,所以希望 console.log 输出引用类型的某一时刻状态是不现实的

    夸张点说,每快照一次,需要保存整个引擎所在内存
    lookas2001
        22
    lookas2001  
       2018-07-14 00:27:38 +08:00 via Android
    输出对象的话是一个引用,然后查看的时候一步一步展开。这点就如 3 楼提示的那样。
    如果输出一个数字一个字符串啥的就不会有这种问题。
    想想都是泪,当时我也遇到过这样的情况,差错查了整整一天。(无奈)
    royzxq
        23
    royzxq  
       2018-07-14 00:45:16 +08:00
    恭喜踩坑 1/?
    wly19960911
        24
    wly19960911  
       2018-07-14 07:05:17 +08:00 via Android
    如果真的想定位当前位置的值,用 debugger 或者 console.log 定位代码然后断点,console.log 出来的值,会异步读取,造成读值的偏差。
    abcbuzhiming
        25
    abcbuzhiming  
    OP
       2018-07-14 09:19:46 +08:00
    @airdge 了解了,谢谢,天坑啊这是
    msg7086
        26
    msg7086  
       2018-07-14 18:00:54 +08:00
    #15 其他语言里连打印对象功能都没有,当然也就没有这个现象了。
    你想想,别的语言里是不是都是打印出字符串的?
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2752 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 32ms · UTC 13:04 · PVG 21:04 · LAX 05:04 · JFK 08:04
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.