Почему это свойство объекта не определено?

#javascript #object #undefined #object-properties

#javascript #объект #не определено #объект-свойства

Вопрос:

Рассмотрим приведенный ниже код. Первый console.log правильно регистрирует изображение, и вы можете увидеть его свойства на изображении ниже. Однако, когда я пытаюсь зарегистрировать одно из его свойств в консоли, я получаю undefined !

 console.log(that.data[0].cards); //works -- see image below
console.log(that.data[0].cards.E); //undefined
console.log(that.data[0].cards['E']); //undefined
console.log(that.data[0].cards.hasOwnProperty('E')); //false

var test = JSON.stringify(that.data[0]);
console.log(test); // {}

for( var key in that.data[0].cards ) {
    console.log('hello????') //doesn't appear in the console
}

console.log( Object.keys( that.data[0].cards ) ); //[]
console.log( that.data[0].cards.propertyIsEnumerable("E") ); //false
console.log( that.data[0].cards.__lookupGetter__( "E" ) ); //undefined
 

Результат в консоли:

введите описание изображения здесь

Есть идеи, что здесь происходит? xml Свойство внутри that.data[0] должно также иметь свойства внутри него — по сути, с тем же именем, что и свойства в cards .

Черт возьми, я получаю то же самое в Firebug (изображение консоли выше — Chrome).

Комментарии:

1. Можете ли вы передать результат JSON.stringify(это)?

2. Не могу вам помочь, если мы не можем воспроизвести поведение. Можете ли вы предоставить JSON?

3. JSON.stringify(that) кажется, ничего не делает, кроме полной остановки скрипта. Не выдает ошибку или что-либо еще, но после вызова ничего не выполняется JSON.stringify(that) . Я обновил свой вопрос, чтобы показать результаты JSON.stringify(that.data[0].cards) , которые просто показывают, что это пустой объект {} .

4. Вы уверены, что на этот раз объект действительно не пустой? Вы не расширили его…

5. Спасибо. Я все еще не могу воспроизвести. Не могли бы вы, возможно, предоставить упрощенный, изолированный тестовый пример на jsfiddle.net ?

Ответ №1:

Я решил проблему. По сути, рассматриваемый объект ( that.data[0].cards ) имеет свои свойства, созданные функцией a() , которая запускается после обработки всех запросов AJAX для необходимых файлов XML. Я разрешаю выполнение запросов асинхронно, используя счетчик для определения в функции success обратного вызова, если a() она еще должна быть вызвана.

После a() запуска функция b() должна выполнять операции that.data[i].cards . Однако b() он выполнялся до a() вызова из a() -за зависимости от асинхронных запросов. Итак, решением было просто выполнить a() вызов b() .

Так что это оказалось довольно простой ошибкой с моей стороны. Что сделало это настолько запутанным, так это тот факт, что вход that.data[0].cards в консоль показал мне, что на самом деле cards объект уже создан, хотя на самом деле он еще не был создан. Итак, консоль предоставляла мне неверную — или, по крайней мере, неясную — информацию.

Спасибо всем за помощь прошлой ночью! Все голоса за 🙂

Комментарии:

1. Сегодня я столкнулся с той же проблемой. Спасибо.

Ответ №2:

Я думаю, что ключи объекта имеют непечатаемые символы, такие могут быть воспроизведены следующим образом:

 var obj = {};
obj["E" String.fromCharCode(15)] = new Array(15);

console.log(obj);

/*Object
E: Array[15]
__proto__: Object*/

console.log(obj.E)

//undefined

console.log( obj["E" String.fromCharCode(15)] )

//[]
 

Редактировать: вы можете увидеть, относится ли это к вашим ключам объекта:

 var realKeys = [];

for( var key in obj ) {
realKeys.push( [].slice.call( key ).map( function(v){return v.charCodeAt(0);} ).join(" ") );
}

//["69 15"] (69 stands for the letter "E" and 15 was the unprintable character I added manually)
 

Редактирование 2: поскольку вы не можете этого сделать, я придумал другой способ проверить, есть ли непечатаемые символы:

Скопируйте ключевую строку следующим образом: (пройдите весь путь как можно дальше с обоих концов, чтобы выбрать любые невидимые символы)

Затем сбросьте свой буфер обмена следующим образом (убедитесь, что вы используете двойные кавычки):

Комментарии:

1. Кажется, дает тот же результат. Я сделал: console.log(that.data[0].cards['E' String.fromCharCode(15)]);

2. Это потому, что ваш объект может иметь другой невидимый символ, чем String.fromCharCode(15) , это может быть 3, 24 или 22 и так далее 🙂

3. @macedison: И по причине @Esailija, пожалуйста, скопируйте / вставьте точный результат JSON.stringify(that.data[0]) , чтобы его можно было исследовать

4. JSON.stringify(that.data[0]) выдает: {"session":"01","xml":{},"cards":{}} . Правда в том, что у xml объекта также должны быть свойства внутри него, с тем же именем cards , что и у объекта на самом деле. Я также обновил свой вопрос, включив в него результаты for предложенного вами цикла, но, похоже, он даже не запускается.

5. Попробуйте console.log( Object.keys( that.data[0].cards ) ); . Если это не сработает, попробуйте console.log( that.data[0].cards.propertyIsEnumerable("E") ); , если это не сработает, попробуйте console.log( that.data[0].cards.__lookupGetter__( "E" ) ); , если это не сработает, просто ссылка на страницу: D