Консоль JavaScript печатает назначенное значение переменной до ее назначения?
Я глубоко смущен поведением JavaScript или консоли Chrome. Может ли кто-нибудь помочь мне понять?
В основном у меня есть следующий код JavaScript, не вложенный внутри какой-либо функции или другой области:
var initial_array = [];
function initialiseArray() {
initial_array = [2, 9, 8, 6, 0, 2, 1];
}
function copyToNewArray() {
var copied_array = [];
console.log("COPIED 1", copied_array);
for (var i = 0; i < initial_array.length; i++) {
var copy = initial_array[i];
copied_array.push(copy);
}
console.log("COPIED 2", copied_array);
}
initialiseArray();
copyToNewArray();
Я ожидал бы COPIED 1
для печати []
- поскольку переменная еще не назначена, но вместо этого она печатает [2, 9, 8, 6, 0, 2, 1]
- то есть значение после того, как оно было назначено.
Почему?
Кстати, если вы заменяете строки 8-11 на initial_array = copied_array
, то RESULTS 1
действительно печатается как []
. Это как-то связано с использованием .push
?
Ответы
Ответ 1
Попробуйте отладить свою проблему в отладчике Chrome script. Поместите точку останова на строку:
for (var i = 0; i < initial_array.length; i++) {
и вы увидите желаемое поведение.
Проблема, с которой вы сталкиваетесь, заключается в том, что вы делаете неверное предположение, что отладчик Chrome "распечатывает" значение сразу, когда на самом деле он выполняет асинхронную процедуру console.log
. Поскольку массивы передаются по ссылке в бэкэнд, когда он действительно идет, чтобы напечатать значение, которое оно теперь является тем, которое вы видите.
Ответ 2
Так как массивы передаются по ссылке, каждое изменение, которое вы делаете, изменяет то, что выводится в консоли. Отчасти это поведение консоли Chrome, частично JavaScript.
Если вы хотите распечатать результат во время вызова console.log
, вы можете вывести его как строку с помощью JSON.stringify
.
console.log("COPIED 1", JSON.stringify(copied_array));
Важное изменение
Кажется, я был в основном неправильным. Как отмечал ДиЭо в комментариях к вопросу, похожий вопрос имеет лучший ответ. Кажется, это только поведение Chrome.
Ответ 3
console.log("COPIED 1", JSON.stringify(copied_array));
Должно быть хорошо для отладки
это ошибка, о которой вы говорили, см. ниже
https://bugs.webkit.org/show_bug.cgi?id=35801
также читали похожие вопросы
Является ли консоль JavaScript Chrome ленивой относительно оценки массивов?
Необычное поведение console.log в инструментах разработчика Chrome
Почему объект javascript показывает разные значения в консоли в Chrome, Firefox, Safari?
Ответ 4
Это то, как массивы отображаются в консоли Chrome, и это по ссылке. Если вы хотите получить точные результаты, конвертируйте в строку:
var initial_array = [];
function initialiseArray() {
initial_array = [2, 9, 8, 6, 0, 2, 1];
}
function copyToNewArray() {
var copied_array = [];
console.log("COPIED 1", copied_array.toString());
for (var i = 0; i < initial_array.length; i++) {
var copy = initial_array[i];
copied_array.push(copy);
}
console.log("COPIED 2", copied_array.toString());
}
initialiseArray();
copyToNewArray();
Вы можете легко проверить это:
var x = [];
console.log(x), x.push(5), x; // outputs [5] and [5]
Ответ 5
Консоль фактически асинхронна. Поскольку вы регистрируете ссылку на объект, к моменту регистрации объекта он уже изменился.
Вы можете клонировать массив, прежде чем регистрировать его, чтобы быть уверенным, что он не будет изменен до его регистрации.
Ответ 6
var initial_array = [];
function initialiseArray() {
initial_array = [2, 9, 8, 6, 0, 2, 1];
}
function copyToNewArray() {
var copied_array = [];
console.log("COPIED 1", copied_array);
alert(copied_array.length);
for (var i = 0; i < initial_array.length; i++) {
var copy = initial_array[i];
copied_array.push(copy);
}
console.log("COPIED 2", copied_array);
}
initialiseArray();
copyToNewArray();
Добавление строки alert(copied_array.length);
покажет правильные результаты.
Случается, что журнал не синхронизируется с выполнением javascript. Когда журнал печатает, значения уже были изменены.
Ответ 7
потому что copied_array
является ссылкой, а console.log выполняется несинхронно, поэтому содержимое массива модифицируется до того, как будет напечатан первый журнал.
вы можете скопировать массив перед печатью
console.log([].concat(copied_array));
Ответ 8
Если вы хотите сохранить функции консоли, такие как расширение объектов в массиве, я предлагаю использовать .slice
, который делает копию массива, которая не изменяется при регистрации:
console.log("COPIED 1", copied_array.slice());