Длина объекта JavaScript
Если у меня есть объект JavaScript, скажем
var myObject = new Object();
myObject["firstname"] = "Gareth";
myObject["lastname"] = "Simpson";
myObject["age"] = 21;
есть ли встроенный или принятый лучший способ получить длину этого объекта?
30 ответов
самый надежный ответ (т. е. который отражает намерение того, что вы пытаетесь сделать, вызывая наименьшее количество ошибок) будет:
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(myArray);
в JavaScript есть своего рода соглашение, которое вы не добавляйте вещи в объект.прототип, потому что он может нарушать перечисления в различных библиотеках. Однако добавление методов в Object обычно безопасно.
вот обновление с 2016 года и широкое развертывание ES5 и за. для IE9+ и всех других современных браузеров с поддержкой ES5+ вы можете использовать Object.keys()
Так что приведенный выше код просто становится:
var size = Object.keys(myObj).length;
это не должно изменять любой существующий прототип с Object.keys()
теперь встроен.
редактировать: объекты могут иметь символические свойства, которые не могут быть возвращены через объект.ключевой метод. Так что ответ был бы неполным без упоминания о них.
тип символа был добавлен к языку для создания уникального идентификаторы свойств объекта. Главное преимущество символьного типа-предотвращение перезаписи.
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
Если вы знаете, что вам не нужно беспокоиться о hasOwnProperty
проверяет, вы можете сделать это очень просто:
Object.keys(myArray).length
Обновлено если вы используете подчеркивания.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;
};
Используйте что-то простое, как:
Object.keys(obj).length
это не должно быть сложно и определенно не требует выполнения другой функции.
вот самое кросс-браузерное решение.
Это лучше, чем принято ответ, потому что он использует собственный объект.ключи, если они существуют. Таким образом, это самый быстрый для всех современных браузеров.
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;
Я не эксперт по JavaScript, но похоже, вам придется перебирать элементы и подсчитывать их, так как у объекта нет метода длины:
var element_count = 0;
for (e in myArray) { if (myArray.hasOwnProperty(e)) element_count++; }
@palmsey: справедливости ради OP, документация JavaScript фактически явно ссылается на использование переменных типа Object таким образом как "ассоциативные массивы".
этот метод получает все имена свойств вашего объекта в массиве, поэтому вы можете получить длину этого массива, равную длине ключей вашего объекта.
Object.getOwnPropertyNames({"hi":"Hi","msg":"Message"}).length; // => 2
чтобы не связываться с прототипом или другим кодом, вы можете создать и расширить свой собственный объект:
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.
конечно, вы всегда можете заменить методы. Но даже если вы это сделаете, ваш код, вероятно, заметно потерпит неудачу, что облегчит отлаживать. ;)
вот как и не забудьте проверить, что свойство не находится в цепочке прототипов:
var element_count = 0;
for(var e in myArray)
if(myArray.hasOwnProperty(e))
element_count++;
вот совершенно другое решение, которое будет работать только в более современных браузерах (IE9+, 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);
в некоторых случаях лучше всего хранить в отдельной переменной. Особенно, если вы добавляете в массив один элемент в одном месте и можете легко увеличить размер. Очевидно, работают намного быстрее, если вам нужно часто проверять размер.
использование:
var myArray = new Object();
myArray["firstname"] = "Gareth";
myArray["lastname"] = "Simpson";
myArray["age"] = 21;
obj = Object.keys(myArray).length;
console.log(obj)
@palmsey: справедливости ради OP, документы javascript фактически явно ссылаются на использование переменных типа Object таким образом как "ассоциативные массивы".
и справедливости ради @palmsey он был совершенно прав, они не являются ассоциативными массивами, они определенно объекты :) - выполнение работы ассоциативного массива. Но что касается более широкой точки, вы определенно, похоже, имеете право на это в соответствии с этой довольно прекрасной статьей, которую я нашел:
JavaScript "Ассоциативные Массивы" Считаются Вредными
но все это, не принято отвечать сама плохая практика?
укажите функцию prototype size () для Object
Если что-нибудь еще добавлено к объекту .прототип, то предложенный код завершится ошибкой:
<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 и проверить тип элементов при их итерации.
Как насчет чего-то вроде этого --
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--; }}
}
Если у нас есть хеш
hash = {"a":" b"," c":"d"};
мы можем получить длину, используя длину ключей, длина хэш:
ключи(хэш).длина
Если вы используете 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 myMap = new Map();
myMap.set("firstname", "Gareth");
myMap.set("lastname", "Simpson");
myMap.set("age", 21);
myMap.size; // 3
вариация на некоторые из вышеперечисленных это:
var objLength = function(obj){
var key,len=0;
for(key in obj){
len += Number( obj.hasOwnProperty(key) );
}
return len;
};
это немного более элегантный способ интеграции hasOwnProp.
если вы не заботитесь о поддержке 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
см. также эта скрипка для демонстрации.
вот другая версия ответа Джеймса Когана. Вместо передачи аргумента просто прототипируйте класс 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.keys(obj).length
на любом объекте, чтобы получить его длину. Объект.keys возвращает массив, содержащий весь объект ключи (свойства), которые могут пригодиться для поиска длины этого объекта, используя длину соответствующего массива. Вы даже можете написать функции для этого. Давайте творческий и писать метод для него также (вместе с более удобным геттером свойство):
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.keys(myobject).length
где myobject является объектом того, что вы хотите длину
вы всегда можете сделать Object.getOwnPropertyNames(myObject).length
чтобы получить тот же результат, что и [].length
даст для нормального проживания.
var myObject = new Object();
myObject["firstname"] = "Gareth";
myObject["lastname"] = "Simpson";
myObject["age"] = 21;
Ниже приведена версия ответа Джеймса Коглана в CoffeeScript для тех, кто отказался от прямого JavaScript :)
Object.size = (obj) ->
size = 0
size++ for own key of obj
size
свойства
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
Как и большинство проблем 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());