Google Chrome console.log() несогласованность с объектами и массивами
Я помогал коллеге отлаживать некоторый код сегодня, и я заметил странное поведение с console.log()
в Google Chrome:
Похоже, что если вы:
-
Создайте вложенный массив (например, [[345, "test" ]])
-
Запишите массив в консоль с помощью console.log()
.
-
Измените одно из значений внутреннего массива, затем console.log()
выведет значение ниже - not значения массива в момент выполнения console.log()
.
JavaScript
var test = [[2345235345,"test"]]
console.log(test);
test[0][0] = 1111111;
// outputs: [[1111111,"test"]]
var testb = {};
testb.test = "test";
console.log(testb);
testb.test = "sdfgsdfg";
// outputs: {"testb":"test"}
var testc = ["test","test2"];
console.log(testc);
testc[0] = "sdxfsdf";
// outputs: ["test","test2"]
Пример JSFiddle
Такое поведение не происходит в Firefox.
Также следует отметить, что если бы я выполнил свой код по строкам в отладчике Chrome, то console.log()
выдаст правильные значения.
Есть ли объяснение этому странному явлению или это просто ошибка с Google Chrome?
EDIT:
Я сузил шаги, чтобы воспроизвести непоследовательное поведение console.log()
:
Если вы добавите этот script на свою страницу:
var greetings=['hi','bye'];
console.log(greetings);
setTimeout(function(){
greetings.push('goodbye');
},3000);
и откройте его в новом окне с открытым окном консоли Chrome , то вывод console.log()
будет отличаться, если вы загрузите страницу с закрытым окном strong > . Здесь показан JSFiddle, который показывает.
В первом случае, когда консольное окно уже открыто, console.log()
выведет текущее значение массива (т.е. два элемента).
Во втором случае, когда консольное окно первоначально закрыто и открыто только после загрузки страницы, console.log()
выдаст более поздние значения массива (т.е. три элемента).
Является ли это ошибкой в функциях Google Chrome console.log()
?
Ответы
Ответ 1
После большого поиска, я обнаружил, что это было сообщено как ошибка, исправленная в Webkit, но, видимо, еще не втянута в Google Chrome.
Насколько я могу судить, проблема была первоначально сообщена здесь: https://bugs.webkit.org/show_bug.cgi?id=35801:
Описание От mitch kramer 2010-03-05 11:37:45 PST
1) создать литерал объекта с одним или несколькими свойствами
2) console.log этот объект, но оставьте его закрытым (не расширяйте его в консоли)
3) измените одно из свойств на новое значение
теперь откройте этот console.log, и вы увидите, что по какой-то причине оно имеет новое значение, даже несмотря на то, что при его создании значение было другим.
Я должен указать, что если вы его откроете, он сохранит правильное значение, если это не ясно.
Отклик от разработчика Chromium:
Комментарий № 2 от Pavel Feldman 2010-03-09 06:33:36 PST
Я не думаю, что мы когда-нибудь это исправим. Мы не можем клонировать объект при сбрасывании его в консоль, и мы также не можем слушать изменения свойств объекта, чтобы сделать его всегда актуальным.
Мы должны убедиться, что ожидаемое поведение ожидается.
Исправление было реализовано два с половиной года спустя 9 августа 2012 года для Webkit (http://trac.webkit.org/changeset/125174), но это похоже, пока не попали в Chrome.
На сегодняшний день сброс объекта (массива) в консоль приведет к тому, что свойства объекта будут читайте о расширении объекта консоли (т.е. лениво). Это означает, что сброс одного и того же объекта во время мутация будет сложной для отладки с помощью консоли.
Это изменение начинает генерировать сокращенные превью для объектов/массивов в момент их регистрирует и передает эту информацию в интерфейсный модуль. Это происходит только тогда, когда интерфейс уже открыт, он работает только для console.log(), а не для взаимодействия с консолью.
Ответ 2
Я нашел обходной путь для этой ошибки/функции.
console.log(JSON.parse(JSON.stringify(myObject)));
Изменить: К сожалению, это не будет работать для не-примитивных значений, таких как функции. Используйте другую утилиту для клонирования.
Пример jQuery:
console.log($.extend({}, myObject));