Как работает console.log? - PullRequest
       41

Как работает console.log?

12 голосов
/ 18 августа 2011

Первый пример:

В следующем примере: 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'));

А вот что выводится на консоль:

Объект ["привет там", "привет там # 2"] undefined

Казалось бы, консоль должна только сказать:

Объект ["Привет!"] undefined

, поскольку второе нажатие не происходило до тех пор, пока значение не было зарегистрировано, поэтому оно не должно отображаться.


Второй пример:

В следующем примере: http://jsfiddle.net/maniator/ScTAW/5/

Я использую ту же самую переменную storage, но регистрируюсь так:

storage.add('hi there')
console.log(storage, storage.get(), (function() {
    storage.add('hi there #2');
    console.log('TESTING');
})());

На консоль выводится:

ИСПЫТАНИЯ
объект ["привет там", "привет там # 2"] undefined

хммммм, что странно сейчас, не так ли? Можно было ожидать увидеть:

Объект ["Привет"] undefined
ИСПЫТАНИЯ

Почему это происходит? Что происходит за кулисами механизма ведения консоли?

Ответы [ 4 ]

18 голосов
/ 18 августа 2011

В большинстве (если не во всех) императивных языках программирования любые аргументы, передаваемые в вызов функции, должны быть оценены перед вызовом функции (так называемая Стремительная оценка ).Кроме того, они обычно оцениваются в порядке слева направо (для C, например, он не определен), однако в обоих примерах порядок, в котором оцениваются аргументы, не имеет значения.Это должно быть довольно очевидно при рассмотрении того, что происходит в деталях:

Как уже упоминалось, прежде чем можно вызвать console.log, сначала нужно выполнить storage.get(), возвращая массив store.Затем будет выполнено storage.add('hi there #2') (или наоборот), поэтому его результат (в данном случае undefined, поскольку add ничего не возвращает) может быть передан в качестве третьего аргумента console.log.Это означает, что когда-то console.log будет вызываться с аргументами (storage, storage.store, undefined), массив store уже содержит "hi there # 2", следовательно, вы получите результаты, которые вы наблюдаете.

Во втором примерерассуждение опять то же самое, вызов функции немного более скрыт.На первый взгляд кажется, что есть функция, переданная в качестве третьего аргумента функции console.log;но на самом деле это вызов функции (наблюдайте за () в конце).Таким образом, storage.add('hi there #2') будет выполнен, затем console.log('TESTING'), а затем результат undefined от выполнения анонимной функции снова будет передан в console.log.

Если вы действительно передали функцию в console.log, это напечатало бы это определение функции, и ничего не выполнило бы.Итак:

storage.add('hi there')
console.log(storage, storage.get(), (function() {
    storage.add('hi there #2');
    console.log('TESTING');
}));

, без () в конце, приводит к:

Object
 ["hi there"] function () {
    storage.add('hi there #2');
    console.log('TESTING');
}

Надеюсь, это немного прояснит ситуацию.

2 голосов
/ 18 августа 2011

Когда вы звоните console.log, как это

console.log(storage, storage.get(), storage.add('hi there #2'));

storage.add('hi there #2') оценивается и возвращаемое значение передается на console.log.Оценка этого приводит к немедленному добавлению элемента массива в store.

То же самое с storage.get() -> store.Таким образом, утверждение становится следующим:

console.log(storage, store, [return value of add which is undefined]);

Когда оно печатается, store оценивается и выводится его содержимое, поэтому вы видите ["hi there", "hi there #2"]


Во второмНапример, сначала анонимная функция оценивается и результаты передаются.

1 голос
/ 18 августа 2011

Ваша функция добавления хранилища полностью оценена до того, как console.log будет вызвано , потому что это параметр.

Это не относится к console.log, так работает каждый императивный язык программирования.

1 голос
/ 18 августа 2011

Все аргументы console.log будут сначала итерированы и оценены, чтобы собрать выходные данные. Поскольку он выполняет итерацию переданных вами аргументов, изменения вносятся в объекты и вызываются функции. После регистратор повторяет аргументы, выводит данные.

Поскольку объекты являются byRef, изменения «второго аргумента» объекта storage.store отражаются в выводе консоли. Поскольку аргументы повторяются, вызов функции в вашем последнем аргументе вызывается перед выводом, поэтому вы видите выходные данные вашего вызова функции до того, как увидите первый console.log вызов. 1010 *

Стоит отметить, что вывод console.log не будет показывать вам объекты такими, какими они есть на момент вызова console.log. То, что вы на самом деле получаете, в случае объектов - это дескриптор ссылки на объект. Таким образом, любые изменения объекта, сделанные после добавления дескриптора к выводу console.log, все равно будут отражены в самом объекте. Поскольку дескриптор указывает только на сам объект, вы получаете не вывод, показывающий состояние объекта, как это было при вызове функции, а скорее прямую ссылку на объект, как сейчас .

...