Иван Сотников 14 сентября 2022

☕ ТОП-5 вопросов и ответов по JavaScript на Stack Overflow за все время

Ответы на пять вопросов, ставящих в тупик каждого второго фронтендера.
2
☕ ТОП-5 вопросов и ответов по JavaScript на Stack Overflow за все время

Stack Overflow — платформа вопросов и ответов на любые темы по программированию. Вы задаете вопрос, а вам отвечает профессиональное сообщество программистов. Можно вопросы не задавать, а найти среди вопросов похожий на ваш. У вопросов и ответов на платформе формируется рейтинг, а ключевым в этом рейтинге является голосование. В статье рассмотрим пять лучших вопросов и ответов по JavaScript и его библиотеках.

1. Как удалить определенный элемент из массива?

Вопрос

Автор: Mateen Ulhaq

Как удалить конкретное значение из массива, а не все, как в этом примере:

        array.remove(value);//удаляет все элементы со значением
    

Ответ

Автор: Kewal Shah

Найдите индекс элемента массива, который вы хотите удалить. Используйте indexOf, а затем удалите этот индекс с помощью splice.

Метод splice() изменяет содержимое массива, удаляя существующие элементы и добавляя новые элементы.

        const array = [2, 5, 9];

console.log(array);

const index = array.indexOf(5);
if (index > -1) { // изменять только содержимое массива, когда элемент найден

  array.splice(index, 1); // 2-й параметр означает удаление только одного элемента
}

// array = [2, 9]
console.log(array);

    

Второй параметр splice — количество удаляемых элементов. Обратите внимание, что splice изменяет массив и возвращает новый массив, содержащий удаленные элементы.

Приведем пример функции. Функция removeItemOnce удаляет только одно вхождение. То есть удаляет первое совпадение 5 из [2,5,9,1,5,8,5]), а функция removeItemAll удаляет все вхождения:

        function removeItemOnce(arr, value) {
  var index = arr.indexOf(value);
  if (index > -1) {
    arr.splice(index, 1);
  }
  return arr;
}

function removeItemAll(arr, value) {
  var i = 0;
  while (i < arr.length) {
    if (arr[i] === value) {
      arr.splice(i, 1);
    } else {
      ++i;
    }
  }
  return arr;
}
// использование
console.log(removeItemOnce([2,5,9,1,5,8,5], 5))
console.log(removeItemAll([2,5,9,1,5,8,5], 5))

    

В TypeScript эти функции могут оставаться безопасными с параметром типа:

        function removeItem<T>(arr: Array<T>, value: T): Array<T> { 
  const index = arr.indexOf(value);
  if (index > -1) {
    arr.splice(index, 1);
  }
  return arr;
}

    
Больше полезных материалов вы найдете на нашем телеграм-канале «Библиотека фронтендера»

2. Как проверить, скрыт ли элемент в jQuery?

Вопрос

Автор: Philip Morton

Как переключить видимость элемента в библиотеке jQuery с помощью .hide(), .show() или .toggle()? Как проверить, является ли элемент видимым или скрытым?

Ответ

Поскольку вопрос относится к одному элементу, этот код подойдет:

        //Проверяет содержимое CSS для отображения: [none|block], игнорирует видимость: [true|false]
$(element).is(":visible");

// То же самое работает со скрытым
$(element).is(":hidden");

    

Мы используем is() jQuery для проверки выбранного элемента, селектора или объекта jQuery.

Этот метод проходит по элементам DOM и ищет совпадение с параметром. Если совпадение есть вернет true, если нет — false.

3. Для чего нужен use strict в JavaScript?

Вопрос

Автор: Mark Rogers

Недавно я пропустил часть своего кода JavaScript через Crockford JSLint, и он выдал следующую ошибку:

Problem at line 1 character 1: Missing "use strict" statement.

Я поискал решение и понял, что разработчики добавляют use strict в свой код. Как только я добавил этот параметр, ошибка перестала появляться. Думаю, что это имеет отношение к интерпретации JavaScript браузером.

Что такое use strict, что это означает, и актуально ли это на сегодняшний день? Понимают ли браузеры use strict?

Ответ

Автор: Pascal Martin

Внутри модулей ECMAScript с операторами импорта, экспорта и классов ES6 use strict всегда включен и не может быть отключен. Чтобы разобраться, можете почитать статью John Resig.

Приведем примеры некоторых интересных замечаний:

Строгий режим — это новая функция ECMAScript 5, которая позволяет поместить программу или функцию в «строгий» рабочий контекст. Этот строгий контекст предотвращает выполнение определенных действий и создает больше исключений.

Строгий режим помогает несколькими способами:

  • Он улавливает некоторые распространенные ошибки кодирования, вызывая исключения.
  • Он предотвращает или выдает ошибки при выполнении относительно «небезопасных» действий (например, при получении доступа к глобальному объекту).
  • Он отключает функции, которые сбивают с толку или плохо продуманы.

Также обратите внимание, что вы можете применить use strict ко всему файлу. Вы также можете использовать его для определенной функции:

Например:

        // Нестрогий код

(function(){
//строгий код
  "use strict";

  // Define your library strictly...
})();

// нестрогий код

    

Это может быть полезно, если вам нужно смешивать старый и новый код. Usestrict поддерживается всеми основными браузерами.


4. Как перенаправить пользователя на другую веб-страницу?

Автор: venkatachalam

Ответ

Нельзя перенаправить пользователя с помощью jQuery.

Для этого jQuery не требуется. А window.location.replace(...) лучше всего имитирует перенаправление HTTP. Если вы хотите имитировать клик по ссылке, используйте location.href. Если вы хотите имитировать перенаправление HTTP, используйте location.replace.

Например:

        //поведение, как перенаправление HTTP
window.location.replace("http://stackoverflow.com");

//поведение при переходе по ссылке
window.location.href = "http://stackoverflow.com";

    

window.location.replace(...) лучше, чем использование window.location.href, потому что replace() не сохраняет исходную страницу в истории сеанса, а это означает, что пользователь не застрянет в бесконечной обратной связи.

5. Как работают замыкания в JavaScript?

Вопрос

Автор: сообщество разработчиков

Как бы вы объяснили замыкания в JavaScript тому, кто знает принципы языка, но не понимает сами замыкания? Я видел пример схемы, приведенный в Википедии, но, к сожалению, это не помогло.

Ответ

Замыкание — это сочетание:

  • Функция и ссылка на внешнюю область действия этой функции (лексическое окружение).
  • Лексическое окружение является частью каждого контекста выполнения и представляет собой карту между именами локальных переменных и значениями.

Каждая функция в JavaScript поддерживает ссылку на свое внешнее окружение. Эта ссылка нужна для настройки контекста выполнения функции.

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

В следующем коде образуется замыкание с лексическим окружением контекста выполнения, созданного при вызове foo, закрывая переменную secret:

        function foo() {
  const secret = Math.trunc(Math.random() * 100)
  return function inner() {
    console.log(`The secret number is ${secret}.`)
  }
}
const f = foo() // `secret` не доступен напрямую извне `foo`
f() // Единственный способ получить `secret`, состоит в том, чтобы вызвать `f`

    

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

Использование замыканий

Замыкания полезны, когда вам нужно приватное состояние, связанное с функцией. В JavaScript до 2015 года не было классов, и до сих пор нет синтаксиса частного поля.

Переменные частного экземпляра

В следующем коде функция toString закрывает детали автомобиля.

        function Car(manufacturer, model, year, color) {
  return {
    toString() {
      return `${manufacturer} ${model} (${year}, ${color})`
    }
  }
}

const car = new Car('Aston Martin', 'V8 Vantage', '2012', 'Quantum Silver')
console.log(car.toString())

    

Функциональное программирование

В следующем коде внутренняя функция замыкается как для fn, так и для args.

        function curry(fn) {
  const args = []
  return function inner(arg) {
    if(args.length === fn.length) return fn(...args)
    args.push(arg)
    return inner
  }
}

function add(a, b) {
  return a + b
}

const curriedAdd = curry(add)
console.log(curriedAdd(2)(3)()) // 5

    

Программирование, ориентированное на события

В следующем коде функция onClick закрывается по переменной BACKGROUND_COLOR.

        const $ = document.querySelector.bind(document)
const BACKGROUND_COLOR = 'rgba(200, 200, 242, 1)'

function onClick() {
  $('body').style.background = BACKGROUND_COLOR
}

$('button').addEventListener('click', onClick)

<button>Set background color</button>
    

Модульность

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

Функции tick и toString закрываются по приватному состоянию и функциям, которые им необходимы для выполнения своей работы. Замыкания позволили нам модулизировать и инкапсулировать наш код.

        let namespace = {};

(function foo(n) {
  let numbers = []

  function format(n) {
    return Math.trunc(n)
  }

  function tick() {
    numbers.push(Math.random() * 100)
  }

  function toString() {
    return numbers.map(format)
  }

  n.counter = {
    tick,
    toString
  }
}(namespace))

const counter = namespace.counter
counter.tick()
counter.tick()
console.log(counter.toString())

    

Примеры

Пример 1

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

        function foo() {
  let x = 42
  let inner = () => console.log(x)
  x = x + 1
  return inner
}

foo()() // logs 43

    

Пример 2

В этом коде три метода log, increment и update закрываются в одной и той же лексической среде. И каждый раз, когда вызывается createObject, создается новый контекст выполнения (фрейм стека) и создается новая переменная x и новый набор функций (журнал и т. д.), которые закрываются поверх этой новой переменной.

        function createObject() {
  let x = 42;
  return {
    log() { console.log(x) },
    increment() { x++ },
    update(value) { x = value }
  }
}

const o = createObject()
o.increment()
o.log() // 43
o.update(5)
o.log() // 5
const p = createObject()
p.log() // 42

    

Пример 3

Если вы используете переменные, объявленные с помощью var, следите за тем, какую переменную вы закрываете. Переменные, объявленные с помощью var – поднимаются.

Это гораздо меньшая проблема в современном JavaScript из-за введения let и const. В следующем коде каждый раз вокруг цикла создается новая внутренняя функция, которая закрывается через i. Но поскольку var i поднимается за пределы цикла, все эти внутренние функции закрываются для одной и той же переменной, а это означает, что конечное значение i (3) печатается три раза.

        function foo() {
  var result = []
  for (var i = 0; i < 3; i++) {
    result.push(function inner() { console.log(i) } )
  }

  return result
}

const result = foo()
// The following will print `3`, three times...
for (var i = 0; i < 3; i++) {
  result[i]() 
}

    

Заключительные пункты

  • Всякий раз, когда функция объявляется в JavaScript, создается закрытие.
  • Возврат функции из другой функции — классический пример замыкания, поскольку состояние внутри внешней функции неявно доступно для возвращаемой внутренней функции даже после того, как внешняя функция завершила выполнение.
  • Всякий раз, когда вы используете eval() внутри функции, используется замыкание. Текст, который вы оцениваете, может ссылаться на локальные переменные функции, а в нестрогом режиме вы даже можете создавать новые локальные переменные, используя eval('var foo = …').
  • Когда вы используете new Function(…) (конструктор Function) внутри функции, он не закрывается в своем лексическом окружении: вместо этого он закрывается в глобальном контексте. Новая функция не может ссылаться на локальные переменные внешней функции.
  • Замыкание в JavaScript похоже на сохранение ссылки на область видимости в точке объявления функции, которая, в свою очередь, сохраняет ссылку на свою внешнюю область видимости и так далее, вплоть до глобального объекта в верхней части цепочки масштабов.
  • Замыкание создается при объявлении функции; это закрытие используется для настройки контекста выполнения при вызове функции.
  • Каждый раз при вызове функции создается новый набор локальных переменных.
***

Мы рассмотрели 5 самых популярных вопросов на Stack Overflow:

1. Как удалить определенный элемент из массива?

2. Как проверить, скрыт ли элемент в JQuery?

3. Для чего нужен use strict в JavaScript?

4. Как перенаправить пользователя на другую веб-страницу?

5. Как работают замыкания в JavaScript?

Материалы по теме

МЕРОПРИЯТИЯ

Комментарии

 
 
15 сентября 2022

Автоматичексим переводчиком переводить плохо, получается местами бред. ("Лошади кушают овёс и сено.", ага)

17 сентября 2022

по секрету, автоматического переводчика здесь ноль

ВАКАНСИИ

Добавить вакансию
Senior Data Scientist LLM
по итогам собеседования
Senior Software Engineer (Java)
от 4500 USD до 6000 USD

ЛУЧШИЕ СТАТЬИ ПО ТЕМЕ

LIVE >

Подпишись

на push-уведомления