Избегайте накладных расходов на обратные вызовы и используйте собственный подход «цикл for-of» с конкретными методами объекта.

В мире JavaScript мы используем объекты каждый день. У нас есть разные подходы, когда нам нужно взаимодействовать через объекты:

1. Для цикла

Наиболее эффективным способом является использование цикла for in для работы с ключами и значениями объекта. Например, мы хотим, чтобы для каждого ключа объекта отображался ключ и соответствующее значение:

const user = {
  name: 'John',
  surname: 'Doe',
  age: 43,
  city: 'LA'
}

for (const key in user) {
  console.log(`${key} = ${user[key]}`);
}

/* results:
"name = John" 
"surname = Doe" 
"age = 43" 
"city = LA"
*/ 

2. Объектные методы

С классом Object мы можем использовать специальные методы для получения всех ключей, значений и записей (пар ключ-значение) из объекта:

Теперь у нас есть два способа использования упомянутых методов:

Теперь давайте посмотрим на пример с обратным вызовом:

const user = {
  name: 'John',
  surname: 'Doe',
  age: 43,
  city: 'LA'
};

Object.keys(user).forEach(key => {
  console.log(`${key}`);
});
/*
"name" 
"surname" 
"age" 
"city" 
*/

Object.values(user).forEach(value => {
  console.log(value);
});
/*
"John" 
"Doe" 
43 
"LA" 
*/

Object.entries(user).forEach(entry => {
  console.log(entry);
});
/*
["name", "John"] 
["surname", "Doe"] 
["age", 43] 
["city", "LA"] 
*/

Как видите, каждый метод объекта возвращает массив в качестве результата, поэтому мы используем метод Array.prototype.forEach() с определенной функцией обратного вызова.

И ниже у нас есть подход с циклом for…of, где мы используем методы объекта для создания цикла for:

for (const key of Object.keys(user)) {
  console.log(`${key}`);
}
/*
"name" 
"surname" 
"age" 
"city" 
*/

for (const value of Object.values(user)) {
  console.log(value);
}
/*
"John" 
"Doe" 
43 
"LA" 
*/

for (const [key, value] of Object.entries(user)) {
  console.log([key, value]);
}
/*
["name", "John"] 
["surname", "Doe"] 
["age", 43] 
["city", "LA"] 
*/

Как видите, в этом решении у нас нет функции обратного вызова for-Each, поэтому у нас есть родной цикл for и метод конкретного объекта — keys(), values() и entry(). Конечно, у нас те же результаты, если вы проверите журналы.

Тест производительности

Давайте соберем все вместе с тестом производительности. Очевидно, что у нас есть ускорение производительности, если мы используем цикл for…of.

const user = {
  name: 'John',
  surname: 'Doe',
  age: 43,
  city: 'LA'
}

const labels = {
  callbackKeys: '---callback keys---',
  loopKeys: '---loop keys---',
  callbackValues: '---callback values---',
  loopValues: '---loop values---',
  callbackEntries: '---callback entries---',
  loopEntries: '---loop entries---'
};

console.time(labels.callbackKeys)
Object.keys(user).forEach(key => {
  console.log(`${key}`);
});
console.timeEnd(labels.callbackKeys)

console.time(labels.callbackValues);
Object.values(user).forEach(value => {
  console.log(value);
});
console.timeEnd(labels.callbackValues);

console.time(labels.callbackEntries);
Object.entries(user).forEach((entry) => {
  console.log(entry);
});
console.timeEnd(labels.callbackEntries)

console.time(labels.loopKeys);
for (const key of Object.keys(user)) {
  console.log(`${key} = ${user[key]}`);
}
console.timeEnd(labels.loopKeys);

console.time(labels.loopValues);
for (const value of Object.values(user)) {
  console.log(value);
}
console.timeEnd(labels.loopValues);

console.time(labels.loopEntries);
for (const [key, value] of Object.entries(user)) {
  console.log([key, value]);
}
console.timeEnd(labels.loopEntries);

// results //
name
surname
age
city
---callback keys---: 4.525ms
John
Doe
43
LA
---callback values---: 0.481ms
[ 'name', 'John' ]
[ 'surname', 'Doe' ]
[ 'age', 43 ]
[ 'city', 'LA' ]
---callback entries---: 1.238ms

name = John
surname = Doe
age = 43
city = LA
---loop keys---: 0.098ms
John
Doe
43
LA
---loop values---: 0.084ms
[ 'name', 'John' ]
[ 'surname', 'Doe' ]
[ 'age', 43 ]
[ 'city', 'LA' ]
---loop entries---: 0.231ms
// end of results //

Заключение

Обратные вызовы — действительно важная концепция в мире JavaScript, но мы можем избежать их, если будем использовать нативные вещи из языка, чтобы повысить производительность. Не поймите меня неправильно, вы все еще можете использовать обратные вызовы при переборе объектов, но с циклом вы избежите накладных расходов на обратные вызовы, и ваш код будет более эффективным.

Спасибо за прочтение.
Надеюсь, вам понравилась статья и вы узнали что-то новое.

Если вам нравятся такие истории и вы хотите продолжать читать мои истории, рассмотрите возможность стать участником среды и моим подписчиком. Это стоит 5 долларов США в месяц и дает вам неограниченный доступ к контенту Medium.

Дополнительные материалы на PlainEnglish.io.

Подпишитесь на нашу бесплатную еженедельную рассылку новостей. Подпишитесь на нас в Twitter, LinkedIn, YouTube и Discord .