Javascript!… Без возражений мы можем легко согласиться с тем, что это модное словечко среди разработчиков как один из самых популярных языков программирования нашего времени. Он завоевал популярность благодаря своей простоте, универсальности и скорости (и это лишь некоторые из них). Около 96% веб-сайтов сегодня используют Javascript на своей клиентской стороне, и, несмотря на то, что изначально он был разработан как клиентский язык, теперь JavaScript пробился и на серверную часть веб-сайтов (благодаря Node. js).

Javascript (JS) — это очень широкий язык программирования, в котором реализовано множество интересных концепций. Эта статья посвящена 5 основным понятиям, которые важны для написания эффективного кода JS.

1. Используйте строгий

Строгий режим позволяет поместить программу или функцию в строгий рабочий контекст. Его главное преимущество заключается в том, что он упрощает отладку. Ошибки кода, которые в противном случае были бы проигнорированы или завершились бы скрытым сбоем, теперь будут генерировать ошибки или вызывать исключения. Это, таким образом, направляет вас быстро к вероятному источнику ошибки.

В файле JS строгий режим включается путем ввода строки "use strict” и размещения ее в верхней части файла или функции.

function myFunction(){
"use strict"
//code to run
};

Особенности использования

я. Использование переменной перед ее объявлением теперь вызывает ошибку. Тем самым предотвращая случайные глобальные и синтаксические ошибки.

II. Это предотвращает использование зарезервированных слов Javascript в качестве имен переменных.

III. В строгом режиме вы не можете удалять функции, переменные или аргументы функций.

"use strict"
var moo = 1;
delete moo;
function foo(){};
delete foo; 
function fcoo(arg)[
  delete arg;
};
//output: SyntaxError: Delete of an unqualified identifier in strict mode.

Какой бы контекст «use strict» ни использовался: глобально в начале файла или локально в функции, следующие блоки кода помещаются в строгий рабочий контекст.

2. Подъем

Подъем — это поведение JS по умолчанию для перемещения объявлений переменных и функций в верхнюю часть охватывающей их области.

"use strict"
console.log(a);
var a = 2;
//output: undefined

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

Когда JS видит строку вроде var a = 2 , она разбивает ее на две строки.

Первая часть — это объявление переменной var a, и оно помещается вверху файла или функции.

Вторая часть присваивает переменной ее значение, то есть a = 2 . JS интерпретирует приведенный выше пример как;

"use strict"
var a ;
console.log(a);
a = 3

На момент регистрации значения a переменная была только объявлена. В JS объявленная переменная, которая не была инициализирована по умолчанию, является неопределенной.

Правило подъема применимо и к функциям. Объявление функции перемещается в верхнюю часть своей области видимости.

myName("Laura");

function myName(name) {
  console.log("My name is " + name);
}
//output: "My name is Laura"

3. Деструктуризация

Деструктуризация — это способ извлечения значений в переменные из данных, хранящихся в объекте или массиве. Это короткий и эффективный способ извлечения значений.

//OBJECT DESTRUCTURING
const person = {
  first: "Laura"
  last: "Cheng"
  age: 20
};
//Don't
const f = person.first;
const l = person.last;
const a = person.age;

// Do
const{ first:f, last:l, age:a } = person;
       OR

const {first, last, age} = person; 
//ARRAY DESTRUCTURING
const fruits = ["mango", "apple", "orange", "pineapple"];
//Don't
const mango= fruits[0];
const apple= fruits[1];

//Do
const [mango, apple, ...others] = fruits
//rest[0] = "orange"
//rest[1] = "pineapple"

Обычно, если массив длиннее списка слева, «лишние» элементы опускаются. Но если мы хотим также извлечь оставшиеся элементы, мы можем добавить еще один параметр, который получает «остальное» с помощью трех точек "..." . Значение others представляет собой массив оставшихся элементов массива.

4. Функция обратного вызова

Функция обратного вызова – это функция A, которая передается в другую функцию B в качестве аргумента, которую затем вызывает B. Обратный вызов выполняет код в ответ на событие.

Обратные вызовы могут быть синхронными или асинхронными. Синхронные операции выполняются по одной. Другими словами, вам нужно дождаться завершения задачи, прежде чем вы сможете перейти к следующей. Во время асинхронных операций вы можете перейти к другой задаче до завершения предыдущей. То есть задачи не последовательные.

Синхронный обратный вызов выполняется во время выполнения родительской функции.

function printName(name) {
console.log("my name is " + name);
}
function greeting(name, fnc) {
console.log("welcome " + name);
fnc(name);
}
console.log(greeting("Laura", printName));
//output
//welcome Laura
//my name is Laura

Асинхронный обратный вызов выполняется после выполнения родительской функции.

Предположим, что нам нужно написать скрипт, который извлекает данные с удаленного сервера и обрабатывает их после получения результата. Однако выполнение запроса к удаленному серверу занимает время в зависимости от скорости сети. Мы можем сделать это, передав функцию process() функции request() и выполнив функцию process() внутри функции request() после завершения запроса, например:

function process(data) {
    console.log(`Processing ${data}`);
}
let url = 'https://www.someserevertovisit.com'
function request(url, callback) {
    setTimeout(() => {
        // script to request data from server
        console.log(`Requesting ${url} ...`);
        
        // process the result
        callback(url);
    }, 2000);
}
console.log(request(url, process));
//output
// Requesting https://www.someserevertovisit.com ...
// Processing https://www.someserevertovisit.com

Когда обратный вызов используется для продолжения выполнения кода после асинхронной операции, обратный вызов называется асинхронной функцией обратного вызова.

5. Обещание

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

Промис имеет 3 возможных состояния:

я. В ожидании — начальное состояние.

II. Решить — операция завершена успешно.

III. Отклонить — операция не удалась.

Промис создается с помощью конструктора промисов

const promise = new Promise((resolve, reject) => {
  // code to carry out operation
  // ...
// return the state
  if (success) {
    resolve(value);
  } else {
    reject(error);
  }
});

Конструктор промисов принимает функцию обратного вызова, которая выполняет асинхронную операцию. Эту функцию иногда называют исполнителем. Исполнитель принимает два аргумента: resolve и reject.

Если обещание выполнено успешно, исполнитель вызовет функцию resolve(). Но в случае ошибки исполнитель вызовет функцию reject(). Например;

let done = true
const isItDone = new Promise((resolve, reject) => {
  if (done) {
    const completed= 'The job is complete'
    resolve(completed)
  } else {
    const incomplete= 'Still working on the job'
    reject(incomplete)
  }
})

В этом примере промис проверяет глобальную константу done, и если она принимает значение true, промис переходит в состояние разрешено: в противном случае выполняется обратный вызов reject, переводя промис в состояние отклонения.

Потребляя обещание: тогда поймай, наконец

  1. Метод then()

Чтобы получить значение обещания, когда оно разрешено или отклонено, вы вызываете метод then() объекта обещания.

promise.then(onFulfilled,onRejected);

Метод then() принимает в качестве параметров две функции.

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

2. Метод catch()

Этот метод используется для получения ошибки только тогда, когда состояние промиса отклонено.

Пример ниже имитирует оба метода then() и catch() в действии.

let done = true
const isItDone = new Promise((resolve, reject) => {
  if (done) {
    const completed= 'The job is complete'
    resolve(completed)
  } else {
    const incomplete= 'Still working on the job'
    reject(incomplete)
  }
})
const checkIfItsDone = () => {
  isItDone
   .then(result => {
      console.log(result)
    })
    .catch(err => {
      console.error(err)
    })
    .finally(_ => {
      console.log("End of promise")
    })
}

3. Метод finally()

Этот метод при использовании всегда вызывается в конце промиса независимо от того, разрешается он или отклоняется. Он сияет в ситуации, когда вы хотите выполнить один и тот же фрагмент кода независимо от результата обещания.

Концепций Javascript очень много, и их нельзя исчерпать в одной статье. В следующих статьях будет объяснено больше. Я надеюсь, что вы нашли этот кусок полезным.