资讯专栏INFORMATION COLUMN

一个“诡异”的console.log()结果

pkwenda / 3315人阅读

摘要:一个诡异的结果在前端开发中,我们都少不了用来输出变量和调试。再看下面一个例子图中的结果,我是在执行了这句话之后才点击的小三角,然而结果却没有变成诡异结果的样子。

一个诡异的结果

在前端开发中,我们都少不了用console.log来输出变量和调试。可是在使用它的过程中,偶尔也会出现一些让我们很费解的行为,如下图:

是不是很诡异:)

这个诡异的行为是怎么来的呢?其实怪我“断章取义”了。控制台上我执行的代码其实是:

注意到展开的数组旁边有一个小i,将鼠标移动上去,会出现提示文字:

Value below was evaluated just now.

简单翻译一下就是:下面展示的值,是刚刚解释执行(evaluated,或者你可以用你熟悉的eval函数来理解这个单词)的结果。

这句话该怎么理解呢?注意到:小i这个提示仅在我们展开数组的时候才会出现,而展开前控制台上展示的确实是一个空数组[]。因此我们可以将展开前后认为是这个值的两个状态。

现在,我们定位到了这个诡异的行为是和展开相关的,那么让我们来实验一下展开这个操作会对log出来的值产生什么影响呢?我们将一行一行地在控制台执行下面三行js代码:

var a = []
console.log(a)
a.push(1, 2, 3, 4, 5)

在执行a.push(1)之前展开[],会得到下面的结果,应该算是一个预期结果:

而在执行a.push(1)之后再展开[],就会得到一开始我给大家看的“诡异”结果了。

现在回过头来看 Value below was evaluated just now. 这句话,其实说的就是,展开后的值,其实是在你点击展开小三角的时候,才 “eval” 出来的。

再看下面一个例子:

图中的结果,我是在执行了a = [1, 2, 3, 4, 5]这句话之后才点击的小三角,然而结果却没有变成“诡异”结果的样子。这是因为后面我更新数组是直接采用变量赋值的方法,相当于修改了变量a的引用,就和变量的引用赋值一样,是影响不了a之前所引用的数组的。

也就是说,console.log()在展开时用于eval的,是变量指向的引用而不是变量本身。

试试其他浏览器

console.log的这个行为并不是chrome限定,在Firefox和Safari中你都能得到同样的行为。

Firefox:

Safari中由于console.log展不开,因此使用console.dir来展开:

Edge下就不是这样子了233:

所以如果你不想要这个“诡异”的结果的话,可以用 Edge 调试哦:)

如果不用Edge呢?

一个正常的思路是,如果能够让console.log直接输出就是展开的,那么这个行为就不会诡异了。

不过很不幸,我没有找到能够做这件事情的API。不过,我们可以借助console.group这个方法,自己造一个展开的结构出来。

/**
 * expandLog
 *
 * @desc 自动展开的 console.log,实现参考:
 * https://stackoverflow.com/questions/10464844/is-there-a-way-to-auto-expand-objects-in-chrome-dev-tools#27610197
 * @author leuisken 
 * @param {Object} obj 需要 log 的对象
 */
function expandLog(obj) {
    if (Array.isArray(obj)) {
        obj.forEach((value, index) => {
            console.group(`${index} : ${type(value)}`);
            expandLog(value);
            console.groupEnd();
        });
    }
    else if (isPlainObject(obj)) {
        Object.keys(obj)
            .forEach(key => {
                const value = obj[key];
                console.group(`${key} : ${type(value)}`);
                expandLog(value);
                console.groupEnd();
            });
    }
    else {
        console.log(obj);
    }
    return;

    /**
     * type
     *
     * @desc 针对部分常见类型给予更好的输出方式
     * @param {Object} obj 传入的对象
     * @return {string} 类型字符串
     */
    function type(obj) {
        const typeofResult = typeof obj;

        if (typeofResult !== "object") {
            return typeofResult;
        }
        else if (obj === null) {
            return "null";
        }
        else if (Array.isArray(obj)) {
            return "Array";
        }
        else if (obj instanceof RegExp) {
            return "RegExp";
        }
        else if (obj instanceof Date) {
            return "Date";
        }
        return "Object";
    }

    /**
     * isPlainObject
     *
     * @desc 即:jQuery.isPlainObject
     * @param {Object} obj 传入的对象
     * @return {boolean} 是否为 PlainObject
     */
    function isPlainObject(obj) {
        if (!obj
            || obj.toString() !== "[object Object]"
            || obj.nodeType
            || obj.setInterval
        ) {
            return false;
        }

        if (obj.constructor
            && !obj.hasOwnProperty("constructor")
            && !obj.constructor.prototype.hasOwnProperty("isPrototypeOf")
        ) {
            return false;
        }

        let key;
        for (key in obj) {}

        return key === undefined || obj.hasOwnProperty(key);
    }
}

这里写这个方法只是示个意,估计一般也不会有谁这么做。。其实很无奈,就和console.logconsole.dir没有提供默认展开的API一样,console.group也没有提供默认收起的API。。。。

题外话

在搜索能否默认展开console.log结果的时候,在Stack Overflow上无意间搜到了这样一个结果。

https://stackoverflow.com/que...

原来 chrome 的 console,也有自己的 console 啊。。

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

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

相关文章

  • 处理for-in用在数组上时候出现诡异现象问题

    摘要:在第一次循环的时候的值为,此后依次为。所以就出现了上面的问题。此外,在下打印的时候可能与在中打印出现不同的结果。尤其是是这种牵扯到数组下标的尽量不要使用来处理,如果非要使用可以做如下处理以避免如上的问题。 问题复现 var arr = [a, b, c]; var sid = [Go]; for (var key in arr) { sid[key + 1] = arr[key...

    huangjinnan 评论0 收藏0
  • 控制台诡异录之展开与缩略不同

    摘要:问题复现最近朋友发给我这样的一个串代码朋友说,这个输出不正确。我表示不信,就试了下从结果看,没毛病啊。朋友说,你展开看看,一看果然有问题缩略状态的显示与展开的显示不同问题思考这个问题的表现是缩略状态下显示原数组,展开状态下显示排序后的数组。 问题复现 最近朋友发给我这样的一个串代码: var arr = [1, 4, 2, 3 ]; console.log(arr); arr.sort...

    opengps 评论0 收藏0
  • 关于JavaScript函数柯里化问题探索

    摘要:函数柯里化关于函数柯里化的问题最初是在忍者秘籍中讲闭包的部分中看到的,相信很多同学见过这样一道和柯里化有关的面试题实现一个函数,使得如下断言能够能够通过简单说就是实现一个求值函数,能够将所有参数相加得出结果。方法返回一个表示该对象的字符串。 函数柯里化   关于函数柯里化的问题最初是在《JavaScript忍者秘籍》中讲闭包的部分中看到的,相信很多同学见过这样一道和柯里化有关的面试题:...

    vboy1010 评论0 收藏0
  • JavaScript This绑定方式导图

    摘要:本文是对加深对的理解一文的导图版翻译中的是一个捉摸不透的东西,它很喜欢变化,很诡异。写在后面的几种绑定规则,归根结底,的套路就是关于几种模式的等价变换形式,知乎上面有大神解答,猛戳这最后是全图附上思维导图的下载链接去有道云笔记下载 本文是对《加深对 JavaScript This 的理解》一文的导图版翻译 JS中的this是一个捉摸不透的东西,它很喜欢变化,很诡异。拥抱变化,接收诡异...

    lbool 评论0 收藏0
  • chrome下Javascript任务机制

    摘要:在第一次循环的时候并没有被赋值,所以是,在第二次循环的时候,定时器其实清理的是上一个循环的定时器。所以导致每次循环都是清理上一次的定时器,而最后一次循环的定时器没被清理,导致一直输出。 Javascript Evet Loop 模型 setTimeout()最短的事件间隔是4mssetInterval()最短的事件间隔是10ms以上这个理论反正我是没有验证过 Exemple 1 --...

    nidaye 评论0 收藏0

发表评论

0条评论

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