Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1041 (permalink)  
Старый 31.03.2015, 18:39
Аватар для nerv_
junior
Отправить личное сообщение для nerv_ Посмотреть профиль Найти все сообщения от nerv_
 
Регистрация: 29.11.2011
Сообщений: 3,924

Array Like Objects
Как правильно и дешево идентифицировать массиво-подообные объекты?
Очевидно, что следующей проверки мало:
var array = [1];
var arrayLike = {0:1, length:1};
var fakeArrayLike = {length:1, height:2};
var window = window;
var fn = function() {};

alert(isArrayLike(array)); // true
alert(isArrayLike(arrayLike)); // true
alert(isArrayLike(fakeArrayLike)); // true | must be false
alert(isArrayLike(window)); // true | must be false
alert(isArrayLike(fn)); // false | must be false
// -------------------

/**
 * @param {*} any
 * @returns {Boolean}
 */
function isArrayLike(any) {
    return isObject(any) && any.hasOwnProperty('length');
}

/**
 * @param {*} any
 * @returns {Boolean}
 */
function isObject(any) {
    return any !== null && typeof any === 'object';
}

Тут написано, что эти объекты должны иметь метод splice, но по факту они его не имеют:
var collection = document.getElementsByTagName('body');
alert(collection.splice);
alert(collection.length);


ангуляр
/**
 * @private
 * @param {*} obj
 * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments,
 *                   String ...)
 */
function isArrayLike(obj) {
  if (obj == null || isWindow(obj)) {
    return false;
  }

  var length = obj.length;

  if (obj.nodeType === 1 && length) {
    return true;
  }

  return isString(obj) || isArray(obj) || length === 0 ||
         typeof length === 'number' && length > 0 && (length - 1) in obj;
}

жуквери
function isArraylike( obj ) {
	var length = obj.length,
		type = jQuery.type( obj );

	if ( type === "function" || jQuery.isWindow( obj ) ) {
		return false;
	}

	if ( obj.nodeType === 1 && length ) {
		return true;
	}

	return type === "array" || length === 0 ||
		typeof length === "number" && length > 0 && ( length - 1 ) in obj;
}


Глядя на все это безобразие, кажется, что нет способа точно определить массиво-подобный объект. Так ли это?
__________________
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук
Ответить с цитированием
  #1042 (permalink)  
Старый 31.03.2015, 18:54
Аватар для МаксимкаНевозбанный
Новичок на форуме
Отправить личное сообщение для МаксимкаНевозбанный Посмотреть профиль Найти все сообщения от МаксимкаНевозбанный
 
Регистрация: 31.03.2015
Сообщений: 9

function likeArray(item) {

  if( !('length' in item) ) return false;

  for(var index = 0; index < item.length; index++){
    if( !(index in item) ) return false;
  }

  return true;
}



илита

Последний раз редактировалось МаксимкаНевозбанный, 31.03.2015 в 19:09.
Ответить с цитированием
  #1043 (permalink)  
Старый 31.03.2015, 19:12
Отправить личное сообщение для Octane Посмотреть профиль Найти все сообщения от Octane  
Регистрация: 10.07.2008
Сообщений: 3,873

Сообщение от МаксимкаНевозбанный
function likeArray(item) {

  if( !('length' in item) ) return false;

  for(var index = 0; index < item.length; index++){
    if( !(index in item) ) return false;
  }

  return true;
}

илита
значит [1,,2] нифига не похоже на массив, да?
Ответить с цитированием
  #1044 (permalink)  
Старый 31.03.2015, 19:13
Аватар для МаксимкаНевозбанный
Новичок на форуме
Отправить личное сообщение для МаксимкаНевозбанный Посмотреть профиль Найти все сообщения от МаксимкаНевозбанный
 
Регистрация: 31.03.2015
Сообщений: 9

Сообщение от Octane
да?
да, в массиве не должно быть прерываний иначе итерации провалятся, в этом и суть проверки на массивоподобность. ваш кэп

к примеру

arr = [];
arr.length = 100;


тоже не считается массивоподобным я осознанно это сделал хотя мог бы проверять чисто (item.length-1 in item)
Ответить с цитированием
  #1045 (permalink)  
Старый 31.03.2015, 19:13
Аватар для Erolast
Профессор
Отправить личное сообщение для Erolast Посмотреть профиль Найти все сообщения от Erolast
 
Регистрация: 24.09.2013
Сообщений: 1,436

Цитата:
Глядя на все это безобразие, кажется, что нет способа точно определить массиво-подобный объект. Так ли это?
Symbol.iterator in object

?

Последний раз редактировалось Erolast, 31.03.2015 в 19:15.
Ответить с цитированием
  #1046 (permalink)  
Старый 31.03.2015, 19:17
Аватар для nerv_
junior
Отправить личное сообщение для nerv_ Посмотреть профиль Найти все сообщения от nerv_
 
Регистрация: 29.11.2011
Сообщений: 3,924

МаксимкаНевозбанный,
Сообщение от nerv_
Как правильно и дешево идентифицировать массиво-подообные объекты?
forEach я и сам могу, но я это делаю уже после идентификации, что более оправданно, нежели для нее
Сообщение от МаксимкаНевозбанный
илита
говоришь
var object = {'12.24': 1, foo: NaN, length: 1};
      
alert(likeArray(object));
      
function likeArray(item) {

  if( !('length' in item) ) return false;

  var keys = Object.keys(item);
  var indexCnt = 0;

  for(var i = 0; i < keys.length; i++){
    var key = keys[i]
    if(+key != key) continue;
    indexCnt++
  }

  return indexCnt === item.length;
}
__________________
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук
Ответить с цитированием
  #1047 (permalink)  
Старый 31.03.2015, 19:24
Аватар для nerv_
junior
Отправить личное сообщение для nerv_ Посмотреть профиль Найти все сообщения от nerv_
 
Регистрация: 29.11.2011
Сообщений: 3,924

Сообщение от Erolast
Symbol.iterator in object
alert(Symbol.iterator in document.getElementsByTagName('body'));
alert(Symbol.iterator in document.querySelectorAll('body'));
__________________
Чебурашка стал символом олимпийских игр. А чего достиг ты?
Тишина - самый громкий звук
Ответить с цитированием
  #1048 (permalink)  
Старый 31.03.2015, 19:30
Аватар для Erolast
Профессор
Отправить личное сообщение для Erolast Посмотреть профиль Найти все сообщения от Erolast
 
Регистрация: 24.09.2013
Сообщений: 1,436

NodeList.prototype[Symbol.iterator] = function*() {
    for (let i = 0; i < this.length; i++) {
        yield this[i];
    }
}
Ответить с цитированием
  #1049 (permalink)  
Старый 31.03.2015, 19:31
Аватар для МаксимкаНевозбанный
Новичок на форуме
Отправить личное сообщение для МаксимкаНевозбанный Посмотреть профиль Найти все сообщения от МаксимкаНевозбанный
 
Регистрация: 31.03.2015
Сообщений: 9

nerv_, я уже изменил свой камент) удаляй свой
Ответить с цитированием
  #1050 (permalink)  
Старый 31.03.2015, 19:33
Аватар для МаксимкаНевозбанный
Новичок на форуме
Отправить личное сообщение для МаксимкаНевозбанный Посмотреть профиль Найти все сообщения от МаксимкаНевозбанный
 
Регистрация: 31.03.2015
Сообщений: 9

function likeArray(item) {
  if( item == null ) return false;
  if( item === window ) return false;
  if( !('length' in item) ) return false;
  if( typeof item === 'function' ) return false;
  if( item.length === 0 ) return true;
  return ( item.length - 1 ) in item
}



вот самый крутой способ и самый быстрый

Последний раз редактировалось МаксимкаНевозбанный, 31.03.2015 в 19:40.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Смишных картинок тред megaupload Оффтопик 3447 03.07.2023 09:47
React'а тред melky Оффтопик 246 13.11.2016 08:07
Webpack'а тред nerv_ Сборка проекта, утилиты 58 07.05.2016 13:46
Смешных историй тред monolithed Оффтопик 11 04.03.2015 04:20
Смишных видео с намеком тред godofjavascript Оффтопик 4 30.12.2012 23:50