Ответов (25)25
Наиболее надежным ответом (т. Е. Отражающим намерение того, что вы пытаетесь сделать, вызывая наименьшее количество ошибок) будет:
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
const myObj = {}
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. Так что ответ был бы неполным без их упоминания.
В язык был добавлен тип символа для создания уникальных идентификаторов свойств объекта. Основное преимущество типа символа - предотвращение перезаписи.
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
Обновлено : если вы используете Underscore.js (рекомендуется, он легкий!), Вы можете просто сделать
_.size({one : 1, two : 2, three : 3});
=> 3
Если нет , и вы не хотите возиться со свойствами объекта по какой-либо причине и уже используете jQuery, плагин также доступен:
$.assocArraySize = function(obj) {
// https://answacode.com/a/6700/11236
var size = 0, key;
for (key in obj) {
if (obj.hasOwnProperty(key)) size++;
}
return size;
};
Вот совершенно другое решение, которое будет работать только в более современных браузерах (Internet Explorer 9+, Chrome, Firefox 4+, Opera 11.60+ и Safari 5.1+).
См. Этот jsFiddle .
Настройте свой класс ассоциативного массива
/**
* @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);
Вот самое кроссбраузерное решение.
Это лучше, чем принятый ответ, потому что он использует собственный 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;
Если вы используете 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>
Решение работает во многих случаях и кроссбраузерно:
Код
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
это не возвращает правильный результат в случае объекта наследования . Для правильного подсчета свойств объекта, в том числе унаследованных, используйте for-in
. Например, с помощью следующей функции (связанный вопрос ):
var objLength = (o,i=0) => { for(p in o) i++; return i }
var myObject = new Object();
myObject["firstname"] = "Gareth";
myObject["lastname"] = "Simpson";
myObject["age"] = 21;
var child = Object.create(myObject);
child["sex"] = "male";
var objLength = (o,i=0) => { for(p in o) i++; return i }
console.log("Object.keys(myObject):", Object.keys(myObject).length, "(OK)");
console.log("Object.keys(child) :", Object.keys(child).length, "(wrong)");
console.log("objLength(child) :", objLength(child), "(OK)");
@palmsey: Справедливости ради, документация JavaScript фактически явно ссылается на использование переменных типа Object таким образом как на «ассоциативные массивы».
И, честно говоря, @palmsey он был совершенно прав. Это не ассоциативные массивы; они определенно объекты :) - они выполняют работу ассоциативного массива. Но что касается более широкой точки зрения, вы определенно имеете на это право, согласно этой довольно хорошей статье, которую я нашел:
«Ассоциативные массивы» JavaScript считаются вредными
Но, судя по всему, принятый ответ сам по себе является плохой практикой?
Укажите функцию размера прототипа () для объекта
Если что-то еще было добавлено в 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>
Я не думаю, что этот ответ должен быть принятым, поскольку ему нельзя доверять, если у вас есть какой-либо другой код, работающий в том же контексте выполнения. Чтобы сделать это надежным образом, вам, безусловно, нужно будет определить метод размера в myArray и проверять тип членов при их итерации.
Я не эксперт по JavaScript, но похоже, что вам придется перебирать элементы и подсчитывать их, поскольку у объекта нет метода длины:
var element_count = 0;
for (e in myArray) { if (myArray.hasOwnProperty(e)) element_count++; }
@palmsey: Справедливости ради, документация JavaScript фактически явно ссылается на использование переменных типа Object таким образом как на «ассоциативные массивы».
Чтобы не связываться с прототипом или другим кодом, вы можете создать и расширить свой собственный объект:
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
Если вы всегда используете метод добавления, свойство length будет правильным. Если вас беспокоит, что вы или другие забудете об его использовании, вы также можете добавить счетчик свойств, опубликованный другими, в метод length.
Конечно, вы всегда можете перезаписать методы. Но даже если вы это сделаете, ваш код, вероятно, выйдет из строя, что упростит отладку. ;)