Ошибка tslint / codelyzer / ng lint: «операторы for (… in…) должны фильтроваться оператором if»

229

Lint сообщение об ошибке:

src / app / detail / edit / edit.component.ts [111, 5]: операторы for (... in ...) должны фильтроваться оператором if

Фрагмент кода (это рабочий код. Он также доступен в разделе проверки формы angular.io ):

for (const field in this.formErrors) {
      // clear previous error message (if any)
      this.formErrors[field] = '';
      const control = form.get(field);

      if (control && control.dirty && !control.valid) {
        const messages = this.validationMessages[field];
        for (const key in control.errors) {
          this.formErrors[field] += messages[key] + ' ';
        }
      }
    }

Есть идеи, как исправить эту ошибку?

Choopage - Джек Бао
источник
Может принять ответ?
Qwertiy

Ответы:

241

Чтобы объяснить реальную проблему , на которую указывает tslint, приведем цитату из документации JavaScript оператора for ... in :

Цикл будет перебирать все перечисляемые свойства самого объекта и тех, которые объект наследует от прототипа своего конструктора (свойства, близкие к объекту в цепочке прототипов, переопределяют свойства прототипов).

Таким образом, в основном это означает, что вы получите свойства, которые вы не ожидаете получить (из цепочки прототипов объекта).

Чтобы решить эту проблему, нам нужно перебирать только собственные свойства объектов. Мы можем сделать это двумя различными способами (как предложено @Maxxx и @Qwertiy).

Первое решение

for (const field of Object.keys(this.formErrors)) {
    ...
}

Здесь мы используем метод Object.Keys (), который возвращает массив собственных перечислимых свойств данного объекта в том же порядке, что и в цикле for ... in (разница в том, что цикл for-in перечисляет свойства в прототип цепи).

Второе решение

for (var field in this.formErrors) {
    if (this.formErrors.hasOwnProperty(field)) {
        ...
    }
}

В этом решении мы перебираем все свойства объекта, включая свойства его цепочки прототипов, но используем метод Object.prototype.hasOwnProperty () , который возвращает логическое значение, указывающее, имеет ли объект указанное свойство как собственное (не унаследованное) свойство для фильтрации унаследованные свойства.

akrabi
источник
2
Я хотел бы отметить, что Object.keysэто ES5. Единственное, что есть у ES6 - это for-of loop. Мы можем перебирать массив в обычном цикле от 0 до его длины, и это будет ES5.
Qwertiy
4
еще раз заметим: если как-то this.formErrorsноль, for...inпросто ничего не делать, пока for ... of Object.keys()выдаст ошибку.
user3448806
я следую второму решению, но все же я вижу сообщение lint. Отключен пух на время.
raj240
2
Почему бы вам не порекомендовать Object.keys(obj).forEach( key => {...}) ?
Бен Карп
268

Более точный способ применения ответа @ Helzgate, возможно, состоит в том, чтобы заменить ваше «for .. in» на

for (const field of Object.keys(this.formErrors)) {
Maxxx
источник
6
Это должен быть принятый ответ, так как он не только решает проблему, но также уменьшает объем стандартного кода по сравнению с дополнительными условиями, такими как if (this.formErrors.hasOwnProperty(field)).
Дениалос
1
Будьте осторожны с ответом, он может сломать ваши коды. Проверьте после того, как вы "исправите" это.
ZZZ
3
Это на самом деле не удаляет ошибку tslint для меня.
HammerN'Songs
7
@ HammerN'Songs проверить , что вы изменили в течение от а для в
Том
та же проблема здесь. ошибка не устранена после использования этого
llamerr
71
for (const field in this.formErrors) {
  if (this.formErrors.hasOwnProperty(field)) {
for (const key in control.errors) {
  if (control.errors.hasOwnProperty(key)) {
Qwertiy
источник
13

используйте Object.keys:

Object.keys(this.formErrors).map(key => {
  this.formErrors[key] = '';
  const control = form.get(key);

  if(control && control.dirty && !control.valid) {
    const messages = this.validationMessages[key];
    Object.keys(control.errors).map(key2 => {
      this.formErrors[key] += messages[key2] + ' ';
    });
  }
});
Helzgate
источник
2

Если поведение for (... in ...) приемлемо / необходимо для ваших целей, вы можете указать tslint разрешить это.

в tslint.json добавьте это в раздел «правил».

"forin": false

В противном случае, @Maxxx имеет правильную идею с

for (const field of Object.keys(this.formErrors)) {
Ник
источник
0

Я думаю, что это сообщение не о том, чтобы избежать использования switch. Вместо этого он хочет, чтобы вы проверили hasOwnProperty. Фон можно прочитать здесь: https://stackoverflow.com/a/16735184/1374488

lukas_o
источник