【发布时间】: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