У меня есть объект JavaScript, есть ли встроенный или общепринятый способ получения длины этого объекта?
const myObject = new Object();
myObject["firstname"] = "Gareth";
myObject["lastname"] = "Simpson";
myObject["age"] = 21;
Самый надежный ответ (то есть, который отражает намерение того, что вы пытаетесь сделать, вызывая при этом наименьшее количество ошибок):
Object.size = function(obj) {
var size = 0, key;
for (key in obj) {
if (obj.hasOwnProperty(key)) size++;
}
return size;
};
// Get the size of an object
var size = Object.size(myObj);
В JavaScript есть своего рода соглашение, что вы не добавляете вещи в Object.prototype , потому что он может нарушать перечисления в различных библиотеках. Однако добавление методов в Object обычно безопасно.
Вот обновление от 2016 года и повсеместное развертывание ES5 и выше. Для IE9 + и всех других современных браузеров с поддержкой ES5 + вы можете использовать следующий Object.keys()
код:
var size = Object.keys(myObj).length;
Это не должно изменять любой существующий прототип, так Object.keys()
как теперь встроен.
Редактировать : Объекты могут иметь символические свойства, которые не могут быть возвращены с помощью метода Object.key. Так что ответ будет неполным без упоминания о них.
Тип символа был добавлен в язык для создания уникальных идентификаторов для свойств объекта. Основным преимуществом типа Symbol является предотвращение перезаписи.
Object.keys
или Object.getOwnPropertyNames
не работает для символических свойств. Чтобы вернуть их вам нужно использовать Object.getOwnPropertySymbols
.
var person = {
[Symbol('name')]: 'John Doe',
[Symbol('age')]: 33,
"occupation": "Programmer"
};
const propOwn = Object.getOwnPropertyNames(person);
console.log(propOwn.length); // 1
let propSymb = Object.getOwnPropertySymbols(person);
console.log(propSymb.length); // 2
Object.keys(obj).length
Я не эксперт по JavaScript, но похоже, что вам придется циклически проходить по элементам и считать их, поскольку у Object нет метода length:
var element_count = 0;
for (e in myArray) { if (myArray.hasOwnProperty(e)) element_count++; }
@palmsey: справедливо для OP, документация JavaScript фактически явно ссылается на использование переменных типа Object таким образом, как «ассоциативные массивы».
Вот как и не забудьте проверить, что свойство не входит в цепочку прототипов:
var element_count = 0;
for(var e in myArray)
if(myArray.hasOwnProperty(e))
element_count++;
@palmsey: справедливости по отношению к OP, документы javascript фактически явно ссылаются на использование переменных типа Object таким образом, как «ассоциативные массивы».
И, честно говоря, @palmsey он был совершенно прав: они не ассоциативные массивы, а определенно объекты :) - выполняющие работу ассоциативного массива. Но что касается более широкой темы, вы определенно имеете на это право в соответствии с этой довольно хорошей статьей, которую я нашел:
JavaScript «Ассоциативные массивы» считается вредным
Но в соответствии с этим, не является ли принятый ответ самой плохой практикой?
Укажите функцию прототипа size () для объекта
Если что-то еще было добавлено в Object .prototype, то предложенный код завершится ошибкой:
<script type="text/javascript">
Object.prototype.size = function () {
var len = this.length ? --this.length : -1;
for (var k in this)
len++;
return len;
}
Object.prototype.size2 = function () {
var len = this.length ? --this.length : -1;
for (var k in this)
len++;
return len;
}
var myArray = new Object();
myArray["firstname"] = "Gareth";
myArray["lastname"] = "Simpson";
myArray["age"] = 21;
alert("age is " + myArray["age"]);
alert("length is " + myArray.size());
</script>
Я не думаю, что ответ должен быть принят, так как ему нельзя доверять, если у вас есть другой код, работающий в том же контексте выполнения. Безусловно, чтобы сделать это надежным способом, вам нужно определить метод size в myArray и проверять тип членов при их итерации.
Если вы знаете, что вам не нужно беспокоиться о hasOwnProperty
проверках, вы можете сделать это очень просто:
Object.keys(myArray).length
Чтобы не связываться с прототипом или другим кодом, вы можете создать и расширить свой собственный объект:
function Hash(){
var length=0;
this.add = function(key, val){
if(this[key] == undefined)
{
length++;
}
this[key]=val;
};
this.length = function(){
return length;
};
}
myArray = new Hash();
myArray.add("lastname", "Simpson");
myArray.add("age", 21);
alert(myArray.length()); // will alert 2
Если вы всегда используете метод add, свойство length будет правильным. Если вы беспокоитесь о том, что вы или другие забыли об его использовании, вы можете добавить счетчик свойств, который другие опубликовали, также в методе length.
Конечно, вы всегда можете переписать методы. Но даже если вы это сделаете, ваш код, вероятно, заметно потерпит неудачу, упрощая отладку. ;)
В некоторых случаях лучше просто сохранить размер в отдельной переменной. Особенно, если вы добавляете в массив по одному элементу в одном месте и можете легко увеличивать размер. Очевидно, это будет работать намного быстрее, если вам нужно часто проверять размер.
Как насчет чего-то вроде этого -
function keyValuePairs() {
this.length = 0;
function add(key, value) { this[key] = value; this.length++; }
function remove(key) { if (this.hasOwnProperty(key)) { delete this[key]; this.length--; }}
}
Вариация некоторых из вышеперечисленных:
var objLength = function(obj){
var key,len=0;
for(key in obj){
len += Number( obj.hasOwnProperty(key) );
}
return len;
};
Это немного более элегантный способ интеграции hasOwnProp.
Обновлено : если вы используете Underscore.js (рекомендуется, он легкий!), То вы можете просто сделать
_.size({one : 1, two : 2, three : 3});
=> 3
Если нет , и вы не хотите возиться со свойствами объекта по какой-либо причине и уже используете jQuery, плагин одинаково доступен:
$.assocArraySize = function(obj) {
// http://stackoverflow.com/a/6700/11236
var size = 0, key;
for (key in obj) {
if (obj.hasOwnProperty(key)) size++;
}
return size;
};
_.size()
было идеальным решением для моего проекта Meteor , поддерживающего underscore.js. Ниже приведена версия ответа Джеймса Коглана в CoffeeScript для тех, кто отказался от прямого JavaScript :)
Object.size = (obj) ->
size = 0
size++ for own key of obj
size
size++ for own key of obj
( own key
синтаксис сахара в CoffeeScript). Использование hasOwnProperty
непосредственно из объекта опасно, поскольку оно нарушается, когда объект действительно обладает таким свойством. Вот другая версия ответа Джеймса Когана. Вместо передачи аргумента просто создайте прототип класса Object и сделайте код чище.
Object.prototype.size = function () {
var size = 0,
key;
for (key in this) {
if (this.hasOwnProperty(key)) size++;
}
return size;
};
var x = {
one: 1,
two: 2,
three: 3
};
x.size() === 3;
Пример jsfiddle: http://jsfiddle.net/qar4j/1/
Object.prototype
- плохая идея. Это совершенно другое решение, которое будет работать только в более современных браузерах (IE9 +, Chrome, Firefox 4+, Opera 11.60+, Safari 5.1+).
Смотрите jsFiddle
Настройте свой ассоциативный класс Array
/**
* @constructor
*/
AssociativeArray = function () {};
// Make the length property work
Object.defineProperty(AssociativeArray.prototype, "length", {
get: function () {
var count = 0;
for (var key in this) {
if (this.hasOwnProperty(key))
count++;
}
return count;
}
});
Теперь вы можете использовать этот код следующим образом ...
var a1 = new AssociativeArray();
a1["prop1"] = "test";
a1["prop2"] = 1234;
a1["prop3"] = "something else";
alert("Length of array is " + a1.length);
length
свойство, любой код, который использовал его, должен был бы гарантировать, что оно не будет пытаться сохранить его length
, но я думаю, что если бы оно было стандартный массив тоже. Переопределение hasOwnProperty
любого объекта, скорее всего, приведет к нежелательному результату. Вот самое кросс-браузерное решение.
Это лучше, чем принятый ответ, потому что он использует нативный Object.keys, если существует. Таким образом, это самый быстрый для всех современных браузеров.
if (!Object.keys) {
Object.keys = function (obj) {
var arr = [],
key;
for (key in obj) {
if (obj.hasOwnProperty(key)) {
arr.push(key);
}
}
return arr;
};
}
Object.keys(obj).length;
Object.keys()
возвращает массив, содержащий имена только тех свойств, которые перечисляются. Если вам нужен массив со ВСЕМИ свойствами, вы должны использовать Object.getOwnPropertyNames()
вместо этого. См developer.mozilla.org/en/docs/Web/JavaScript/Reference/...Если у нас есть хэш
hash = {"a": "b", "c": "d"};
мы можем получить длину, используя длину ключей, которая является длиной хеша:
ключи (хэш) .length
Как и большинство проблем JavaScript, есть много решений. Вы можете расширить объект, который, к лучшему или худшему, работает как словарь многих других языков (+ граждане первого класса). В этом нет ничего плохого, но другой вариант - создать новый объект, который соответствует вашим конкретным потребностям.
function uberject(obj){
this._count = 0;
for(var param in obj){
this[param] = obj[param];
this._count++;
}
}
uberject.prototype.getLength = function(){
return this._count;
};
var foo = new uberject({bar:123,baz:456});
alert(foo.getLength());
Этот метод получает все имена свойств вашего объекта в массиве, поэтому вы можете получить длину этого массива, равную длине ключей вашего объекта.
Object.getOwnPropertyNames({"hi":"Hi","msg":"Message"}).length; // => 2
Свойство
Object.defineProperty(Object.prototype, 'length', {
get: function () {
var size = 0, key;
for (key in this)
if (this.hasOwnProperty(key))
size++;
return size;
}
});
использование
var o = {a: 1, b: 2, c: 3};
alert(o.length); // <-- 3
o['foo'] = 123;
alert(o.length); // <-- 4
Простое решение:
var myObject = {}; // ... your object goes here.
var length = 0;
for (var property in myObject) {
if (myObject.hasOwnProperty(property)){
length += 1;
}
};
console.log(length); // logs 0 in my example.
Если вы используете AngularJS 1.x, вы можете сделать все так же, как AngularJS, создав фильтр и используя код из любого другого примера, такого как:
// Count the elements in an object
app.filter('lengthOfObject', function() {
return function( obj ) {
var size = 0, key;
for (key in obj) {
if (obj.hasOwnProperty(key)) size++;
}
return size;
}
})
использование
В вашем контроллере:
$scope.filterResult = $filter('lengthOfObject')($scope.object)
Или по вашему мнению:
<any ng-expression="object | lengthOfObject"></any>
Вы всегда можете сделать так, Object.getOwnPropertyNames(myObject).length
чтобы получить тот же результат, [].length
что и для обычного массива.
Object.keys()
возвращает массив, содержащий имена только тех свойств, которые перечисляются. Если вам нужен массив со ВСЕМИ свойствами, вы должны использовать Object.getOwnPropertyNames()
вместо этого. См developer.mozilla.org/en/docs/Web/JavaScript/Reference/...Если вам не нужна поддержка Internet Explorer 8 или ниже, вы можете легко получить количество свойств в объекте, выполнив следующие два шага:
- Запустите либо,
Object.keys()
чтобы получить массив, содержащий имена только тех свойств, которые являются перечисляемыми, или,Object.getOwnPropertyNames()
если вы хотите также включить имена свойств, которые не перечислимы. - Получить
.length
свойство этого массива.
Если вам нужно сделать это более одного раза, вы можете заключить эту логику в функцию:
function size(obj, enumerablesOnly) {
return enumerablesOnly === false ?
Object.getOwnPropertyNames(obj).length :
Object.keys(obj).length;
}
Как использовать эту функцию:
var myObj = Object.create({}, {
getFoo: {},
setFoo: {}
});
myObj.Foo = 12;
var myArr = [1,2,5,4,8,15];
console.log(size(myObj)); // Output : 1
console.log(size(myObj, true)); // Output : 1
console.log(size(myObj, false)); // Output : 3
console.log(size(myArr)); // Output : 6
console.log(size(myArr, true)); // Output : 6
console.log(size(myArr, false)); // Output : 7
Смотрите также эту скрипку для демонстрации.
Если вам нужна ассоциативная структура данных, которая показывает ее размер, лучше использовать карту вместо объекта.
const myMap = new Map();
myMap.set("firstname", "Gareth");
myMap.set("lastname", "Simpson");
myMap.set("age", 21);
myMap.size; // 3
Использование:
var myArray = new Object();
myArray["firstname"] = "Gareth";
myArray["lastname"] = "Simpson";
myArray["age"] = 21;
obj = Object.keys(myArray).length;
console.log(obj)
Решение работает для многих случаев и кросс-браузер:
Код
var getTotal = function(collection) {
var length = collection['length'];
var isArrayObject = typeof length == 'number' && length >= 0 && length <= Math.pow(2,53) - 1; // Number.MAX_SAFE_INTEGER
if(isArrayObject) {
return collection['length'];
}
i= 0;
for(var key in collection) {
if (collection.hasOwnProperty(key)) {
i++;
}
}
return i;
};
Примеры данных:
// case 1
var a = new Object();
a["firstname"] = "Gareth";
a["lastname"] = "Simpson";
a["age"] = 21;
//case 2
var b = [1,2,3];
// case 3
var c = {};
c[0] = 1;
c.two = 2;
использование
getLength(a); // 3
getLength(b); // 3
getLength(c); // 2
Вы можете просто использовать Object.keys(obj).length
любой объект, чтобы получить его длину. Object.keys возвращает массив, содержащий все ключи объекта (свойства), которые могут пригодиться для определения длины этого объекта по длине соответствующего массива. Вы даже можете написать функцию для этого. Давайте проявим творческий подход и напишем для него метод (вместе с более удобным свойством getter):
function objLength(obj)
{
return Object.keys(obj).length;
}
console.log(objLength({a:1, b:"summit", c:"nonsense"}));
// Works perfectly fine
var obj = new Object();
obj['fish'] = 30;
obj['nullified content'] = null;
console.log(objLength(obj));
// It also works your way, which is creating it using the Object constructor
Object.prototype.getLength = function() {
return Object.keys(this).length;
}
console.log(obj.getLength());
// You can also write it as a method, which is more efficient as done so above
Object.defineProperty(Object.prototype, "length", {get:function(){
return Object.keys(this).length;
}});
console.log(obj.length);
// probably the most effictive approach is done so and demonstrated above which sets a getter property called "length" for objects which returns the equivalent value of getLength(this) or this.getLength()
Мы можем найти длину объекта с помощью:
Object.values(myObject).length
Немного опоздал к игре, но хороший способ добиться этого (только для IE9 +) - определить магический метод получения свойства length:
Object.defineProperty(Object.prototype, "length", {
get: function () {
return Object.keys(this).length;
}
});
И вы можете просто использовать его так:
var myObj = { 'key': 'value' };
myObj.length;
Дал бы 1
.
Просто используйте это, чтобы получить length
:
Object.keys(myObject).length
myArray
var myObject = new Object();
myObject["firstname"] = "Gareth";
myObject["lastname"] = "Simpson";
myObject["age"] = 21;
- Object.values (MyObject) .length
- Object.entries (MyObject) .length
- Object.keys (MyObject) .length
var myObject = {}; for (let i=0; i<10000000; i++) myObject[i] = i;
Object.keys(obj).length