【问题标题】:Why do javascript calls to console.log affect logic flow?为什么对 console.log 的 javascript 调用会影响逻辑流?
【发布时间】:2015-09-04 19:54:01
【问题描述】:

在 Javascript 中,我使用 console.log 进行调试。看起来,一旦我把逻辑搞定了,我就可以自信地取出调试语句而不会影响逻辑。这是相反的证据。 (试探性地说,因为我可能错了!)首先,程序;请寻找一长串星号。 (我自己在看一本教科书;这是那里的一项作业,但你没有帮我做作业。我正在努力理解这门语言!)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Why is call to console.log needed?</title>
    <script type="text/javascript">
        /** IterAbstract: Constructor for a means of visiting every object in
         * a collection.
         *
         * @param arr: the collection, either an ArraySeq or a RangeSeq
         * @returns
         *   method getNext returns (1) (most likely) a member of arr;
         *     possibly the value undefined, if that's in the collection, or
         *     (2) the value undefined, an tentative indication that there
         *     are no further elements.
         *   method getAtEnd returns (1) true, if no further elements remain,
         *     or (2) false, if further elements remain to be sent.
         * @constructor IterAbstract
         * Users should use only the two methods.
         */
        function IterAbstract (arr) {
            this.arr = arr;
            this.last = this.arr.length - 1;
            this.lastSent = null;
            this.atEnd = false;
        }
            /* *************************
               The focus is the call to console.log at the start of the
               function following these comments.
               ************************* */
            /* The expected behavior of this file is that when function
               logFive receives a two-element array, there will be three calls
               to getNext. The first call uses the return commented "return
               for the first element"; it returns the first element of the
               array and logFive puts it on console.log. The second call uses
               the return commented "return for all other elements"; that
               return makes all other elements available for logFive to record
               on console.log. The third call creates the unambiguous "we're
               past the end of file" signal (a combination of this.atEnd=true
               and returning the undefined value); it uses the return
               commented "after-the-end return".

               When logFive gets an array [1, 2], we expect to see two calls
               to console.log, one with each element.

               When logFive gets an array [null, undefined], we expect the same,
               though with different (and admittedly squirrely) elements
               demonstrated.

               Good: When the subject call to console.log occurs (not commented
               out), the expected behavior occurs. Though there are interspersed
               lines starting "getNext", we see rows with the four expected
               outputs: 1, 2, null, and undefined.

               Bad: When we comment out the subject call to console.log, we see
               three of the four expected rows: 1, 2, and null.

               There is a series of three other calls to console.log designed
               to show us which exit the code uses. They have been commented out
               before; let's uncomment the them.

               Good: Though there are interspersed lines starting "getNext", we
               see the four expected rows. The code is using the expected
               returns.

               Why do these debugging calls to console.log affect actual logic
               flow? (he he) Where's the user error here?
            */
        IterAbstract.prototype.getNext = function () {
            console.log("getNext   this.lastSent=" + this.lastSent +
                    "   this.atEnd=" + this.atEnd);
            if (this.lastSent === this.last) {
                //console.log("getNext after-the-end return   this.lastSent="+
                //        this.lastSent+"   this.last="+this.last);
                this.atEnd = true;
                return undefined; // after-the-end return
            }
            if (this.lastSent === null) {
                this.lastSent = 0;
                //console.log("getNext first exit   element=0");
                return this.arr[0]; // return for the first element
            }
            var sent=this.lastSent+1;
            //console.log("getNext normal exit   element="+sent);
            return this.arr[++this.lastSent]; // return for all other elements
        };
        IterAbstract.prototype.getAtEnd = function () { return this.atEnd; };
        /** logFive: Shows the first five elements of a collection on
         * console.log; less, if the collection has less.
         * @param arr: the collection, either an ArraySeq or a RangeSeq
         */
        function logFive (arr) {
            var iterArr = new IterAbstract(arr);
            /*console.log("after Constructor   iterArr.arr="+iterArr.arr+
                    "   iterArr.last="+iterArr.last+
                    "   iterArr.lastSent="+iterArr.lastSent+
                    "   iterArr.atEnd="+iterArr.atEnd); */
            var response;
            for (i=0; i < 5; i++) {
                //console.log("start iter   i="+i+
                //        "   iterArr.atEnd="+iterArr.atEnd);
                response = iterArr.getNext();
                /*console.log("iter i="+i+"   response="+response+
                        "   iterArr.atEnd="+iterArr.atEnd);*/
                if (response === undefined && iterArr.getAtEnd()) return;
                //console.log("iter normal exit");
                console.log(response);
        }   }
        function ArraySeq ( arr ) {
            return arr;
        }
        console.log ("logFive(new ArraySeq([1, 2]));");
        logFive(new ArraySeq([1, 2]));
        // → 1
        // → 2
        console.log ("logFive(new ArraySeq([null,undefined]);");
        logFive(new ArraySeq([null,undefined]));
        // → null
        // → undefined
    </script>
</head>
<body>
<p>Output for this program goes to console.log.</p>

<p>In Firefox, press Ctrl-Shift-K to see that output.</p>

<p>In Chrome, press Ctrl-Shift-J to see that output.</p>
</body>
</html>

该代码的输出是:

logFive(new ArraySeq([1, 2]));
getNext   this.lastSent=null   this.atEnd=false 
1 
getNext   this.lastSent=0   this.atEnd=false 
2 
getNext   this.lastSent=1   this.atEnd=false 
logFive(new ArraySeq([null,undefined]); 
getNext   this.lastSent=null   this.atEnd=false 
null 
getNext   this.lastSent=0   this.atEnd=false 
undefined 
getNext   this.lastSent=1   this.atEnd=false

甜!快完成了。这正是我想要的,除了以“getNext”开头的行。让我们在 getNext 的开头注释掉对 console.log 的调用。然后,输出变为:

logFive(new ArraySeq([1, 2])); 
1 
2 
logFive(new ArraySeq([null,undefined]); 
null

嘿!不公平。 我需要另一行,“未定义”。去哪儿了?

也许如果我能弄清楚每次使用的 return 语句,我会学到一些有趣的东西。我将在 getNext 中的每个退出点取消对 console.log 的三个调用的注释。现在,输出变为:

logFive(new ArraySeq([1, 2])); 
getNext first exit   element=0 
1 
getNext normal exit   element=1 
2 
getNext after-the-end return   this.lastSent=1   this.last=1 
logFive(new ArraySeq([null,undefined]); 
getNext first exit   element=0 
null 
getNext normal exit   element=1 
undefined 
getNext after-the-end return   this.lastSent=1   this.last=1

叹息。如果我能把调试语句放进去,我就能得到正确的输出,除了多余的垃圾。

胡思乱想?提前致谢!

【问题讨论】:

  • 我无法重现,在评论console.log() 语句后,我仍然有undefined 行。
  • 这里,起码用jsfiddle开始,这样大家都能看到代码。我把它粘贴到这个:jsfiddle.net/daylight/5wxkx2a9
  • 铬?它的控制台出现了问题,所有日志都不可靠。
  • 确实可以重现firefox默认控制台上的行为(出于Maxime答案中提到的原因),FireBug控制台不分组null和undefined,这可能是不是每个人都可以重现的原因。尚未测试 Chrome

标签: javascript prototype console.log


【解决方案1】:

Firefox 将 null 和 undefined 组合在一起。在它们之间放置另一个 console.log 会强制它们不再按分组。当显示多个类似的日志时,分组有助于保持控制台更整洁,例如在循环中。

这里 Firefox 将所有内容记录在一个单独的行上,因为没有任何背靠背行是相似的:

但由于某种原因,它认为 null 和 undefined 足够相似,可以在它们背靠背时组合在一起:

你的输出是正确的。 Firefox 的显示方式并非如此。

【讨论】:

    猜你喜欢
    • 2015-05-04
    • 2015-04-13
    • 1970-01-01
    • 2013-04-28
    • 1970-01-01
    • 2015-12-20
    • 1970-01-01
    • 2020-01-05
    相关资源
    最近更新 更多