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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 00:53:36  来源:igfitidea点击:

How does console.log work?

javascriptconsolelogging

提问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 storagevariable 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.logcan be called, storage.get()has to be executed first, returning the storearray. Then storage.add('hi there #2')will be executed (or the other way round), so its result (in this case undefined, since adddoes not return anything) can be passed as the third argument to console.log. This means that the once console.logwill be called with the arguments (storage, storage.store, undefined), the storearray 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.logfunction; 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 undefinedresult 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.loglike 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 storeimmediately.

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, storeis 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.logis 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.logwill 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.storeobject 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.logcall.

因为对象是 byRef,所以您对storage.store对象的“第二个参数”更改会反映在控制台输出中。因为参数是迭代的,最后一个参数中的函数调用在输出被汇编之前被调用,所以你会在看到第一次console.log调用的输出之前看到函数调用的输出。

It is worth noting, then, that the output of console.logis 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的输出后对对象所做的任何更改仍将反映在对象本身中。由于句柄仅指向对象本身,因此您不会得到显示对象状态的输出,就像调用函数时一样,而是像现在一样指向对象的实时链接。