позиция-из-которой
, сколько-выдрать
, вставить-этого
, вставить-ещё
, ...function swap(arr, from, to) {
// выдёргиваем:
const A = arr.splice(from, 1)[0];
const B = arr.splice(to-1, 1)[0];
// -1 т.к. массив стал короче после первой операции
// вставляем
arr.splice(from, 0, B); // 0 - ничего не вырезаем, только вставляем
arr.splice(to, 0, A);
}
splice()
function swap(arr, from, to) {
// выдёргиваем-копируем:
const A = arr[from];
const B = arr[to];
// вставляем-заменяем
arr[from] = B;
arr[to] = A;
}
const zip = arr => arr
.reduce((agg, c) => {
const iR = agg.indexOf(c + 1);
const iL = agg.lastIndexOf(c - 1);
if (!!~iR && !!~iL) agg.splice(iL, 2); // закрыли дырку
else if (!!~iR) agg[iR] = c; // сдвинули границу
else if (!!~iL) agg[iL] = c; // то же
else { // вставляем сироту - найти позицию сразу после меньшего
let pos = 0;
while (pos < agg.length && agg[pos] < c) pos++;
agg.splice(pos, 0, c, c); // вставляем дважды
}
return agg;
}, [])
.reduce((agg, c, i, arr) => {
if (!(i&1)) agg.push(arr[i+1] === c ? c : [c, arr[i+1]].join('-'));
return agg;
}, [])
.join(', ')
;
[ 0, 5, 8, 9, 11, 11 ]
indexOf()
и lastIndexOf()
на самописный поиск, останавливающийся на элементе, бОльшем или меньшем искомого.console.log(this); // window
this
не принимает значение кнопки, а наследует его из внешнего кода. В данном случае, глобального, поэтому this === window
this
будет нажатой кнопкой. Так бы работало без стрелочной функции, если по-старинке передавали function(evt) {}
0. Получение ключа доступа
Для работы с виджетами в сообществе необходимо получить токен сообщества с правом доступаapp_widget
при помощи события VK Connect: VKWebAppGetCommunityAuthToken в приложении с типом VK Mini Apps.
npm install @vkontakte/vk-connect
index.js
:import connect from '@vkontakte/vk-connect';
// Sending event to client
connect
.sendPromise('VKWebAppGetCommunityAuthToken', {
"app_id": 6909581, // id вашего свежесозданного mini App
"group_id": 1, // id группы, где вы админ, куда виджет
"scope": "app_widget"
})
.then(data => {
// Обработка события в случае успеха
console.log(data);
})
.catch(error => {
//Обработка событияв случае ошибки
});
Затем, наверное, webpack'ом билдится готовый скрипт, который подгружается в браузер.// Set the name of the hidden property and the change event for visibility
var hidden, visibilityChange;
if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
hidden = "hidden";
visibilityChange = "visibilitychange";
} else if (typeof document.msHidden !== "undefined") {
hidden = "msHidden";
visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden !== "undefined") {
hidden = "webkitHidden";
visibilityChange = "webkitvisibilitychange";
}
var videoElement = document.getElementById("videoElement");
// If the page is hidden, pause the video;
// if the page is shown, play the video
function handleVisibilityChange() {
if (document[hidden]) {
videoElement.pause();
} else {
videoElement.play();
}
}
// Warn if the browser doesn't support addEventListener or the Page Visibility API
if (typeof document.addEventListener === "undefined" || hidden === undefined) {
console.log("This demo requires a browser, such as Google Chrome or Firefox, that supports the Page Visibility API.");
} else {
// Handle page visibility change
document.addEventListener(visibilityChange, handleVisibilityChange, false);
// When the video pauses, set the title.
// This shows the paused
videoElement.addEventListener("pause", function(){
document.title = 'Paused';
}, false);
// When the video plays, set the title.
videoElement.addEventListener("play", function(){
document.title = 'Playing';
}, false);
}
[10, 20, 30, 50, 235, 3000].filter(n => !!~[1,2,5].indexOf(+n.toString()[0]))
// результат [ 10, 20, 50, 235 ]
Вывод на экран пилите самостоятельно.filter()
оставит только те элементы, для которых функция внутри вернёт true
. Функция аргумент (в скобках) применяется по очереди к каждому элементу массива (числу).+
).indexOf()
ищет полученную первую цифру в массиве допустимых: 1, 2, 5 и возврашает его индекс (0, 1 или 2) или -1, если не найдено.~
из -1 сделает 0. А из любого другого числа (из 0, 1 или 2) – сделает ненулевое число. Два !!
это два булевых оператора отрицания. Из аргумента делают true
или false
. Из 0 получится false
, из любого другого true
. Таким образом связка !!~
и indexOf()
даёт ответ на вопрос найден или не найден? getRangeAt(0)
Range
есть свойства startOffset
и endOffset
– то, про что спрашиваете.value=""
function reset() {
[...document.querySelectorAll('section.main input[type="text"]')]
.forEach( el => el.value='' )
;
}
document.getElementsByClassName('budget_day-value')[0]
document.querySelector('.budget_day-value')
<label>
, и либо указывать id
инпута в атрибуте for=""
, либо включать инпут внутрь этого лейбла. Так клик по названию поля сделает фокус внутри этого поля.
Замыкания
В программировании есть общий термин: «замыкание», – которое должен знать каждый разработчик.
Замыкание – это функция, которая запоминает свои внешние переменные и может получить к ним доступ. В некоторых языках это невозможно, или функция должна быть написана специальным образом, чтобы получилось замыкание. Но, как было описано выше, в JavaScript, все функции изначально являются замыканиями (есть только одно исключение, про которое будет рассказано в Синтаксис "new Function
").
То есть, они автоматически запоминают, где были созданы, с помощью скрытого свойства[[Environment]]
и все они могут получить доступ к внешним переменным.
Когда на собеседовании фронтенд-разработчик получает вопрос: «что такое замыкание?», – правильным ответом будет определение замыкания и объяснения того факта, что все функции в JavaScript являются замыканиями, и, может быть, несколько слов о технических деталях: свойстве[[Environment]]
и о том, как работает лексическое окружение.
const onClick = event => {
const nodeList = document.querySelectorAll('.item');
for (let i=0; i<nodeList.length; i++ ) {
nodeList[i].style = (nodeList[i] === event.target ? 'background:red' : 'background:green');
};
}
.item {background: green } // по умолчанию все зелёные
.item-red {background: red } // тот самый
// clickedEl — item, по которому кликнули
[...document.querySelectorAll('.item')].forEach(el => {
if (clickedEl === el) el.classList.add('item-red');
else el.classList.remove('item-red');
});
while()
и не for()
— может, прокатит?// случайные:
const myArray = [...Array(3)]
.map(
row =>
[...Array(3)]
.map(
el => Math.floor(Math.random() * 10)
)
)
;
// диагональ, где оба индекса равны:
const diagonal = myArray
.map(
(row, rowIndex) =>
row
.map(
(el, elIndex) => rowIndex === elIndex ? 1 : 0
)
)
;
/**
* асинхрота с запросом. Возвращает Promise
*/
const doAsyncStuff = (urlIter, urlSite) => new Promise((resolve, reject) => {
needle.get(urlIter, (err, result) => { // Сама асинхронная функция
if (err) reject(err);
$('.product-card__link')
.each((i, val) => prodLink.push(urlSite + $(val).attr("href")));
resolve();
})
})
/**
* Тот самый цикл
* @param {number} quanPage число страниц
*/
const doStuff = async quanPage => {
for(let i = 1; i <= quanPage; i++) {
let urlIter = urlSite + i; // Ссылка, которая создается с каждой новой итерацией
await doAsyncStuff(urlIter, urlSite); // Ждём-с!
}
}
doStuff(10);
if(check){
if(true || check) { // временно убрали проверку заполнения всех полей. TODO убрать костыль
function sub(form_id){
$("#img_loader").val($("#files").find("img").attr("src"));
$.ajax({
type: 'POST',
url: '/php.php',
data: $('#'+form_id).serialize(),
success: function(data) {
$("#recall_wrapper").html("<p class='title_recall'>Ваш отзыв успешно отправлен</p>");
setTimeout(() => window.location.href='/recalls_ok.htm', 1000); // перекидывать не сразу, а через 1 сек
},
error: function(xhr, str){
$("#status__send").text('Возникла ошибка: ' + xhr.responseCode);
}
});
}
FooSearchComponent
, в который через props из родителя передаём реактивное свойство foo
:Vue.component(
"FooSearchComponent",
{
props: ['foo'],
template: '<div>
<a
href="#"
@click="searchFoo(foo)"
>
{{ foo }}
</a>
</div>',
methods: {
searchFoo: function(search) {
console.log("searchFoo:", search);
},
}
}
);
searchFoo()
в который параметром передаётся свойство (реактивное, извне) foo