Как мне перечислить свойства объекта JavaScript?
Я действительно хочу перечислить все определенные переменные и их значения, но я узнал, что определение переменной фактически создает свойство объекта окна.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Достаточно просто:
for(var propertyName in myObject) {
// propertyName is what you want
// you can get the value like this: myObject[propertyName]
}
Теперь вы не получите частные переменные таким образом, потому что они недоступны.
Обновлено: @bitwiseplatypus верно, что, если вы не используете метод hasOwnProperty(), вы получите наследуемые свойства - однако я не знаю, почему любой, кто знаком с объектно-ориентированным программированием, ожидал бы чего-то меньшего! Обычно тот, кто поднимает этот вопрос, подвергается предупреждениям Дугласа Крокфорда по этому поводу, которые до сих пор меня немного смущают. Опять же, наследование является нормальной частью объектно-ориентированных языков и, следовательно, частью JavaScript, несмотря на то, что он является прототипом.
Теперь, с учетом сказанного, hasOwnProperty()является полезен для фильтрации, но нам не нужно выдавать предупреждение, как будто есть что-то опасное в получении унаследованных свойств.
Обновлено еще раз: @bitwiseplatypus вызывает ситуацию, которая может возникнуть, если кто-то добавит свойства / методы к вашим объектам в момент времени позже, чем когда вы изначально написали свои объекты (через его прототип) - хотя это правда, что это может вызвать неожиданное поведение, Я лично не считаю это своей проблемой. Просто вопрос мнения. Кроме того, что, если я спроектирую вещи таким образом, что я буду использовать прототипы во время создания своих объектов, но при этом у меня будет код, который выполняет итерацию по свойствам объекта, а мне нужны все унаследованные свойства? Я бы не стал использовать hasOwnProperty(). Затем, скажем, кто-то позже добавит новые свойства. Это моя вина, если в этот момент дела идут плохо? Я так не думаю. Я думаю, что именно поэтому jQuery, например, определил способы расширения его работы (через jQuery.extend и jQuery.fn.extend).
Интересно, что это не работает для свойств геттера, определенных с помощью Object.defineProperty, но работает для прямых геттеров. Смотрите мой jsfiddle.
Я думаю, что люди наиболее удивлены тем, что for(x in {}) вообще что-либо перечисляет, поскольку это похоже на простую итерацию словарного ключа. Это очень неожиданно и определенно заслуживает особого предупреждения.
Я хотел бы знать, сколько раз люди действительно сталкивались с этой ошибкой. Однажды я это сделал, и это было действительно легко заметить. Предупреждение при обучении циклов JS for in - это хорошо, поэтому при необходимости вы можете фильтровать унаследованные свойства. Засорение моих for loop слепыми проверками hasOwnProperty для людей, не имеющих базовых знаний о JS, оправдано нет.
@GlennMaynard, в данном случае он вообще ничего не перечисляет. jsbin.com/vupexuva/1/edit
Примечание: это не сработает для некоторых объектов, таких как Error, потому что свойства не перечисляются. В таких случаях вы хотите использовать Object.getOwnPropertyNames.
как насчет объектов, у которых есть функция? Также возвращается содержимое функции ???
Я нашел случай, когда это не работает: в объектах подтипа MouseEvent, во время «Item [Sub]». Я проверил, что Sub - это строка. Консоль Firefox выдает сообщение об ошибке «NS_ERROR_NOT_IMPLEMENTED». Я понятия не имею, какая функция не реализована.
Этот ответ был первоначально написан чуть более 10 лет назад. Ситуация меняется, и неудивительно, что подходы, включающие что-либо подобное, следует проверять на предмет постоянной точности. Я полагаю, что это одно из самых очевидных ограничений StackOverflow - во многих случаях данные устаревают. :)
@DavidSpector Предполагается, что это сообщение относится к тому факту, что итераторами являются не реализована для свойств объекта, только для элементов массива. Вероятно, вы пропустили let / var и написали for (thing in set) { ... }, что легко сделать.
Я нашел это ... for (property in object) { // do stuff } перечислит все свойства и, следовательно, все глобально объявленные переменные объекта окна ..
Используйте цикл for..in для перечисления свойств объекта, но будьте осторожны. Перечисление вернет свойства не только перечисляемого объекта, но также из прототипов любых родительских объектов.
var myObject = {foo: 'bar'};
for (var name in myObject) {
alert(name);
}
// results in a single alert of 'foo'
Object.prototype.baz = 'quux';
for (var name in myObject) {
alert(name);
}
// results in two alerts, one for 'foo' and one for 'baz'
Чтобы избежать включения унаследованных свойств в ваше перечисление, проверьте hasOwnProperty():
for (var name in myObject) {
if (myObject.hasOwnProperty(name)) {
alert(name);
}
}
Редактировать: Я не согласен с утверждением JasonBunting о том, что нам не нужно беспокоиться о перечислении унаследованных свойств. Существует опасность является при перечислении унаследованных свойств, которых вы не ожидаете, потому что это может изменить поведение вашего кода.
Не имеет значения, существует ли эта проблема на других языках; Дело в том, что он существует, а JavaScript особенно уязвим, поскольку модификации прототипа объекта влияют на дочерние объекты, даже если модификация происходит после создания экземпляра.
Вот почему JavaScript предоставляет hasOwnProperty(), и поэтому вы должны использовать его, чтобы гарантировать, что сторонний код (или любой другой код, который может изменить прототип) не сломает ваш. Помимо добавления нескольких дополнительных байтов кода, в использовании hasOwnProperty() нет недостатков.
Сторонниками hasOwnProperty обычно являются те, кто: а) пострадал от агрессивных общих библиотек [например: Prototype.js около 2003 года] или б) построил основы для гетерогенных систем (подумайте: веб-порталы). Всем остальным следует просто обернуть hasOwnProperty шаблоном итератора и пойти за пивом.
Этот шаблон необходим и используется, потому что javascript объединяет «объекты-актеры» с «таблицами хеширования». когда объект является описание поведения и черт, тогда применяются обычные правила, вы хотите знать о свойствах объекта, не беспокоясь о том, как они туда попали. Если, с другой стороны, вы используете объект как хранилище значений ключей, то вас, скорее всего, будут интересовать только фактические ключи, которые фактически хранятся в объекте. Другие свойства случайны и не отражают фактическое состояние объекта. Другие языки разрешают это различие с помощью различных типов.
как я понимаю, как новичок js, как Object.prototype.baz = 'quux'; изменяет объект myObject?
Если вы пытаетесь перечислить свойства, чтобы написать новый код для объекта, я бы рекомендовал использовать отладчик, например Firebug, чтобы увидеть их визуально.
Другой удобный метод - использовать Prototype Object.toJSON () для сериализации объекта в JSON, который покажет вам как имена свойств, так и значения.
var data = {name: 'Violet', occupation: 'character', age: 25, pets: ['frog', 'rabbit']};
Object.toJSON(data);
//-> '{"name": "Violet", "occupation": "character", "age": 25, "pets": ["frog","rabbit"]}'
for (prop in obj) {
alert(prop + ' = ' + obj[prop]);
}
Лучший простой ответ, который объясняет все необходимое для базового использования.
добавление obj [prop] #FTW
Думаю, уместен пример случая, который застал меня врасплох:
var myObject = { name: "Cody", status: "Surprised" };
for (var propertyName in myObject) {
document.writeln( propertyName + " : " + myObject[propertyName] );
}
Но, к моему удивлению, результат
name : Cody
status : Surprised
forEach : function (obj, callback) {
for (prop in obj) {
if (obj.hasOwnProperty(prop) && typeof obj[prop] !== "function") {
callback(prop);
}
}
}
Почему? Другой скрипт на странице расширил прототип объекта:
Object.prototype.forEach = function (obj, callback) {
for ( prop in obj ) {
if ( obj.hasOwnProperty( prop ) && typeof obj[prop] !== "function" ) {
callback( prop );
}
}
};
Интересно, я полагаю, это означает, что при переопределении функции forEach можно НЕ вызывать обратный вызов, что может привести к прерыванию перечисления свойств.
Да, я хочу сказать, что другой сценарий мог добавить что угодно к прототипу объекта. Такого рода изменения могут быть, а могут и не быть, а добавленные методы могут делать что угодно. Я не утверждаю, что этот пример forEach хорош - просто сценарий может сделать что-то, что изменит результаты for .. in для других сценариев.
В свете современных тенденций в разработке JavaScript изменение прототипа любого из базовых типов кажется мне плохим решением; Есть и другие способы снять шкуру с большинства кошек, которые в первую очередь побуждают людей делать это.
Я согласен, но если это сделает другой код, я все равно не хочу, чтобы мой сломался.
@cyberhobo - Понятно, но кто заставил его сломаться? Ты? Нет, кто-то, кто пришел после, и не обдумал и не знал, во что ввязывается, и поэтому они идиоты. Любой достойный специалист по JavaScript знает, что изменение прототипов любого объекта, изначально не принадлежащего им, потенциально может сыграть с огнем.
Похоже, что об этой ошибке известно больше разработчиков. Я был бы счастлив, если бы мой пример оказался совершенно неуместным и новым разработчикам, которые учатся перечислять объекты, даже не нужно было знать о такой возможности.
Раскрасьте меня в сомнение относительно вашего удивления.
Стандартный способ, который уже предлагался несколько раз:
for (var name in myObject) {
alert(name);
}
Однако в Internet Explorer 6, 7 и 8 есть ошибка в интерпретаторе JavaScript, из-за которой некоторые ключи не пронумерованы. Если вы запустите этот код:
var obj = { toString: 12};
for (var name in obj) {
alert(name);
}
Если появится предупреждение «12» во всех браузерах, кроме IE. IE просто проигнорирует этот ключ. Затронутые ключевые значения:
isPrototypeOfhasOwnPropertytoLocaleStringtoStringvalueOfЧтобы быть действительно безопасным в IE, вы должны использовать что-то вроде:
for (var key in myObject) {
alert(key);
}
var shadowedKeys = [
"isPrototypeOf",
"hasOwnProperty",
"toLocaleString",
"toString",
"valueOf"
];
for (var i=0, a=shadowedKeys, l=a.length; i<l; i++) {
if map.hasOwnProperty(a[i])) {
alert(a[i]);
}
}
Хорошая новость заключается в том, что EcmaScript 5 определяет функцию Object.keys(myObject), которая возвращает ключи объекта в виде массива, и некоторые браузеры (например, Safari 4) уже реализуют ее.
Простой код JavaScript:
for(var propertyName in myObject) {
// propertyName is what you want.
// You can get the value like this: myObject[propertyName]
}
jQuery:
jQuery.each(obj, function(key, value) {
// key is what you want.
// The value is in: value
});
Если вы используете библиотеку Underscore.js, вы можете использовать функцию ключи:
_.keys({one : 1, two : 2, three : 3});
=> ["one", "two", "three"]
Object.keys () - не стандартный способ сделать это.
Вот как перечислить свойства объекта:
var params = { name: 'myname', age: 'myage' }
for (var key in params) {
alert(key + " = " + params[key]);
}
В современных браузерах (ECMAScript 5) для получения всех перечислимых свойств вы можете:
Object.keys (объект) (Проверьте ссылку, чтобы получить фрагмент для обратной совместимости в старых браузерах)
Или получить также неперечислимые свойства:
Object.getOwnPropertyNames (объект)
Проверьте таблицу совместимости ECMAScript 5
Дополнительная информация: Что такое перечислимый атрибут?
Object.getOwnPropertyNames(obj) - это то, что вам нужно, если вы имеете дело с каким-либо объектом Error (например, TypeError), потому что свойства не перечислимые.
Python dict имеет метод ключей, и это действительно полезно. Я думаю, что в JavaScript у нас может быть что-то такое:
function keys(){
var k = [];
for(var p in this) {
if (this.hasOwnProperty(p))
k.push(p);
}
return k;
}
Object.defineProperty(Object.prototype, "keys", { value : keys, enumerable:false });
Обновлено: Но ответ @ carlos-ruana работает очень хорошо. Я протестировал Object.keys (окно), и результат оказался тем, что я ожидал.
ИЗМЕНИТЬ через 5 лет: не рекомендуется расширять Object, потому что это может конфликтовать с другими библиотеками, которые могут захотеть использовать keys на своих объектах, и это приведет к непредсказуемому поведению в вашем проекте. Ответ @ carlos-ruana - это правильный способ получить ключи от объекта.
Вы можете использовать for цикла.
Если вы хотите использовать массив:
Object.keys(object1)
Ref. Object.keys ()
Я все еще новичок в JavaScript, но я написал небольшую функцию для рекурсивной печати всех свойств объекта и его потомков:
getDescription(object, tabs) {
var str = "{\n";
for (var x in object) {
str += Array(tabs + 2).join("\t") + x + ": ";
if (typeof object[x] === 'object' && object[x]) {
str += this.getDescription(object[x], tabs + 1);
} else {
str += object[x];
}
str += "\n";
}
str += Array(tabs + 1).join("\t") + "}";
return str;
}
Я думаю, что @bitwiseplatypus просто говорит «будь осторожен». Я считаю, что обучение JavaScript for / in должно сопровождаться упоминанием hasOwnProperty () и других менее чем очевидных крайних случаев прототипного наследования.