JavaScript: скрытие методов-прототипов в цикле for? - PullRequest
43 голосов
/ 10 июля 2009

Допустим, я добавил несколько методов-прототипов в класс Array:



Array.prototype.containsKey = function(obj) {
    for(var key in this)
        if (key == obj) return true;
    return false;
}

Array.prototype.containsValue = function(obj) {
    for(var key in this)
        if (this[key] == obj) return true;
    return false;
}

затем я создаю ассоциативный массив и пытаюсь перебрать его ключи:



var arr = new Array();
arr['One'] = 1;
arr['Two'] = 2;
arr['Three'] = 3;

for(var key in arr)
   alert(key);

это возвращает пять пунктов:

  -One
  -Two
  -Three
  -containsKey
  -containsValue

но я хочу (ожидаю?) Только три. Я подхожу к этому неправильно? Есть ли способ «спрятать» методы-прототипы? или я должен делать что-то по-другому?

Ответы [ 6 ]

48 голосов
/ 10 июля 2009

Вы можете использовать метод JavaScript hasOwnProperty , чтобы добиться этого в цикле, например:

for(var key in arr) {
    if (arr.hasOwnProperty(key)) {
        ...
    }
}

Ссылка: Эта статья в блоге YUI .

47 голосов
/ 10 апреля 2014

Вы можете достичь желаемого результата с другого конца, сделав методы-прототипы не перечисляемыми:

Object.defineProperty(Array.prototype, "containsKey", {
  enumerable: false,
  value: function(obj) {
      for(var key in this)
        if (key == obj) return true;
      return false;
    }
});

Обычно это работает лучше, если у вас есть контроль над определениями методов, и, в частности, если у вас нет контроля над тем, как ваш код будет вызываться другими людьми, что является распространенным предположением при разработке кода библиотеки.

4 голосов
/ 10 июля 2009

Javascript не поддерживает ассоциативные массивы так, как вы думаете. http://ajaxian.com/archives/javascript-associative-arrays-considered-harmful

for (var i in .. получает все свойства объекта (массив - это просто еще один объект), поэтому вы видите другие объекты, которые вы ему создали.

Как следует из статьи, вы должны использовать объект:


var assoc = {'One' : 1, 'Two' : 2};
assoc['Three'] = 3;

for(var key in assoc)
   alert(key+' => '+assoc[key]);
2 голосов
/ 10 июля 2009

Вы могли бы сделать это:

for(var key in arr)
{
   if (typeof(arr[key]) == "function")
      continue;
   alert(key);
}

Но это плохой обходной путь

1 голос
/ 22 марта 2018

Метод 1 : используйте Object.keys (который не возвращает свойства прототипа) & loop

Object.keys(arr); // ['One', 'Two', 'Three']
Object.keys(arr).forEach(key => console.log(key))

Метод 2 : hasOwnProperty внутри цикла for.

 for(var key in arr) {
   if (arr.hasOwnProperty(key)) {
     ...
   }
 }
0 голосов
/ 10 июля 2009

Для высокопроизводительной итерации по массивам JavaScript используйте цикл for или while. Николас Закас обсуждает наиболее эффективные варианты перебора массивов в своем Tech Talk Speed ​​Up Your JavaScript .

Ваша лучшая ставка, вероятно, примерно такая:

for (var i = collection.length - 1; i >= 0; i--) {
  if (obj == collection[i]) return true;
}

Этот подход будет оптимальным по нескольким причинам:

  • Выделена только одна локальная переменная
  • Свойство length коллекции доступно только один раз при инициализации цикла
  • Каждая итерация, локальная сравнивается с константой (i >= 0) вместо другой переменной
...