☕ ТОП-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?