Javascript console.log 如何工作?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7111612/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How does console.log work?
提问by Naftali aka Neal
First Example:
第一个例子:
In the following example: http://jsfiddle.net/maniator/ScTAW/4/
I have this js:
在以下示例中:http: //jsfiddle.net/maniator/ScTAW/4/
我有这个 js:
var storage = (function () {
var store = [];
return {
"add": function (item) {
store.push(item);
},
"get": function () {
return store;
}
};
}());
storage.add('hi there')
console.log(storage, storage.get(), storage.add('hi there #2'));
And here is what gets printed to the console:
这是打印到控制台的内容:
Object ["hi there", "hi there #2"] undefined
对象 ["hi there", "hi there #2"] 未定义
One would think that the console should only say:
有人会认为控制台应该只说:
Object ["hi there"] undefined
对象 ["hi there"] 未定义
becase the second push did nothappen until after the value was logged, therefore it should not be displayed.
becase的第二推也不会发生,直到该值被记录之后,因此它不应该被显示。
Second Example:
第二个例子:
In the following example: http://jsfiddle.net/maniator/ScTAW/5/
在以下示例中:http: //jsfiddle.net/maniator/ScTAW/5/
I am using the same storage
variable but I log like so:
我使用相同的storage
变量,但我这样记录:
storage.add('hi there')
console.log(storage, storage.get(), (function() {
storage.add('hi there #2');
console.log('TESTING');
})());
What gets printed to the console is:
打印到控制台的内容是:
TESTING
Object ["hi there", "hi there #2"] undefined
测试
对象 ["hi there", "hi there #2"] 未定义
hmmmm well that is odd now isnt it? One could expect to see:
嗯,这很奇怪,不是吗?人们可能会看到:
Object ["hi there"] undefined
TESTING
对象 ["hi there"] 未定义的
测试
Why is this happening? What is going on behind the scenes of the console logging mechanism?
为什么会这样?控制台日志记录机制的幕后发生了什么?
回答by Janick Bernet
In most (if not all) imperative programming languages, any arguments passed to a function call have to be evaluated before the function can be called (so called Eager evaluation). Also, they are in general evaluated in order from left to right (for C for instance it's undefined), however in both examples the order in which the arguments are evaluated does not matter. This should be pretty obvious when looking at what happens in detail:
在大多数(如果不是全部)命令式编程语言中,传递给函数调用的任何参数都必须在调用函数之前进行评估(所谓的Eager Evaluation)。此外,它们通常按从左到右的顺序进行评估(例如,对于 C 而言,它是未定义的),但是在这两个示例中,评估参数的顺序并不重要。在查看详细发生的情况时,这应该非常明显:
As mentioned, before console.log
can be called, storage.get()
has to be executed first, returning the store
array. Then storage.add('hi there #2')
will be executed (or the other way round), so its result (in this case undefined
, since add
does not return anything) can be passed as the third argument to console.log
. This means that the once console.log
will be called with the arguments (storage, storage.store, undefined)
, the store
array already contains "hi there #2", hence producing the results you observe.
如前所述,beforeconsole.log
可以被调用,storage.get()
必须先执行,返回store
数组。然后storage.add('hi there #2')
将被执行(或相反),因此其结果(在本例中undefined
,因为add
不返回任何内容)可以作为第三个参数传递给console.log
. 这意味着console.log
将使用参数调用一次(storage, storage.store, undefined)
,store
数组已经包含“hi there #2”,因此产生您观察到的结果。
In the second example the reasoning is again the same, the function call is just a bit more obscured. On first look it looks there is a function passed as a 3rd argument to the console.log
function; but it's actually a function call (observer the ()
at the end). So storage.add('hi there #2')
will be executed, then console.log('TESTING')
and then the undefined
result from the anonymous function execution will be again passed to console.log
.
在第二个示例中,推理再次相同,只是函数调用更加模糊。乍一看,它看起来有一个函数作为第三个参数传递给console.log
函数;但它实际上是一个函数调用(观察()
最后)。Sostorage.add('hi there #2')
将被执行,然后匿名函数执行console.log('TESTING')
的undefined
结果将再次传递给console.log
.
If you did actually pass a function to console.log
, it would print that function definition, and not execute anything. So:
如果您确实将函数传递给console.log
,它将打印该函数定义,并且不执行任何操作。所以:
storage.add('hi there')
console.log(storage, storage.get(), (function() {
storage.add('hi there #2');
console.log('TESTING');
}));
, without the ()
at the end, results in:
,没有()
在最后,结果:
Object
["hi there"] function () {
storage.add('hi there #2');
console.log('TESTING');
}
I hope this makes things a bit clearer.
我希望这能让事情更清楚一些。
回答by Mrchief
When you're calling console.log
like this
当你调用console.log
这样
console.log(storage, storage.get(), storage.add('hi there #2'));
storage.add('hi there #2')
is evaluated and the return valueis passed to console.log
. Evaluating it causes the array item to be added to store
immediately.
storage.add('hi there #2')
被评估并将返回值传递给console.log
. 评估它会导致store
立即添加数组项。
Same thing with storage.get()
-> store
. So effectively, the statement becomes:
与storage.get()
->相同store
。如此有效,语句变为:
console.log(storage, store, [return value of add which is undefined]);
When it prints, store
is evaluated and its content are output which is why you see ["hi there", "hi there #2"]
当它打印时,store
进行评估并输出其内容,这就是您看到的原因["hi there", "hi there #2"]
In your second example also, the anonymous function is evaluated first and the results are passed on.
在你的第二个例子中,匿名函数首先被评估,结果被传递。
回答by Blindy
Your storage adding function is completely evaluated beforeconsole.log
is calledbecause it's a parameter.
您的存储添加函数在console.log
调用之前已完全评估,因为它是一个参数。
This is not specific to console.log
, this is how every imperative programming language works.
这不是特定于 的console.log
,这就是每种命令式编程语言的工作方式。
回答by Chris Baker
All arguments to console.log
will first be iterated and evaluated in order to assemble the output. As it is iterating the arguments you've passed, changes are made to objects and functions are called. Afterthe logger has iterated the arguments, it outputs the data.
console.log
将首先迭代和评估所有参数以组合输出。由于它正在迭代您传递的参数,因此会对对象进行更改并调用函数。在记录器迭代参数后,它输出数据。
Because objects are byRef, your "second argument" changes to the storage.store
object are reflected in the console output. Because the arguments are iterated, the function call in your last argument is called beforethe output is assembled, so you see the output from your function call before you see the output of the first console.log
call.
因为对象是 byRef,所以您对storage.store
对象的“第二个参数”更改会反映在控制台输出中。因为参数是迭代的,最后一个参数中的函数调用在输出被汇编之前被调用,所以你会在看到第一次console.log
调用的输出之前看到函数调用的输出。
It is worth noting, then, that the output of console.log
is not going to show you objects as they exist at the time of the call to console.log
. What you actually get, in the case of objects, is a reference handle to the object. Thus, any changes to the object made after the handle has been added to console.log
's output will still be reflected in the object itself. Since the handle only points to the object itself, you are not getting output showing the state of the object as it was when you called the function, but rather a live link to the object as it is now.
值得注意的是, 的输出console.log
不会向您显示在调用console.log
. 在对象的情况下,您实际得到的是对象的引用句柄。因此,在将句柄添加到console.log
的输出后对对象所做的任何更改仍将反映在对象本身中。由于句柄仅指向对象本身,因此您不会得到显示对象状态的输出,就像调用函数时一样,而是像现在一样指向对象的实时链接。