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?
Комментарии