Ответы пользователя по тегу JavaScript
  • Почему js не обработал столкновение?

    dollar
    @dollar
    Потому что код плохо написан.
    Из-за этого высока вероятность бага.

    Писать код нужно так, словно завтра его будет проверять человек в 10 раз глупее вас, и по итогам будет начислять вам зарплату. То есть если не поймет, как он устроен, то зарплата, соответственно, ноль. Это позволило бы не только вам самому легко найти или сразу увидеть ошибку, но и показать код другу-программисту.

    На самом деле даже без других людей это правило тоже важно. Потому что вы-сегодня и вы-завтра - это два разных человека. И чем дальше во времени, тем больше разница. Через месяц или, скажем, через полгода вы уже сами не сможете разобраться в своем коде. Что такое x? А что значит aex? Будут примерно такие вопросы. Что делает функция game, за что отвечает? Ведь по названию не понятно, а комментариев нет. Где главный цикл игры? Только после полного прочтения кода и долгих попыток разобраться, удастся понять логику структуры кода, но в таком случае проще заново написать с нуля.

    Вам нужно обратить внимание в первую очередь на:
    • то, как вы называете переменные и функции (нужно осмысленно)
    • наличие комментариев, помогающих понять код


    Начните с этой статьи в Википедии, и если захотите продолжить в том же направлении, то закончите какой-нибудь книгой по теме. Есть много таких книг, достаточно прочитать хотя бы одну. Например, "Совершенный код" (Макконнелл) или "Рефакторинг" (Фаулер).
    Ответ написан
  • Возможно ли полностью отделить движок?

    dollar
    @dollar
    Если ваша цель - просто попробовать, то лучше что-нибудь попроще сделать.

    Например, для консоли написать змейку с нуля. Там же основа элементарная. А по мере развития фантазии, основной код уже будет обрастать именно вашими хотелками, будь то консоль или что угодно ещё.
    Ответ написан
  • Как из строки вычленить и добавить в массив все элементы, перечисленные через запятую?

    dollar
    @dollar
    array = city.split(',').map(s=>s.trim());

    или короче (но менее красиво и менее надежно):
    array = city.split(', '); //с пробелом
    Ответ написан
  • Что не так со значением ключа объекта?

    dollar
    @dollar
    Проблема в том, что объекты присваиваются по ссылке.

    То есть, скорее всего, в вашем массиве есть одинаковые (как вы выразились) объекты в буквальном смысле, то есть указывающие на одну и ту же область памяти.
    const obj = {id: 3};
    const items = [obj, obj];
    items[0].id = 7;
    console.log(items[1].id); //7
    items[1].id = 9;
    console.log(JSON.stringify(items)); //[{"id":9},{"id":9}]
    Ответ написан
  • Почему в JS взятие остатка от деления -11 на 10 возвращает -1?

    dollar
    @dollar
    Потому что проще всего реализуется в широком диапазоне подходов аппаратного деления и лучше всего способствует многоэтапному делению в длинной арифметике.

    Можете почитать википедию (секцию про программирование), чтобы узнать, как это работает в разных языках программирования. Конкретно в JavaScript знак остатка всегда совпадает со знаком делимого. То есть если делимое - отрицательное число, то и остаток будет отрицательным.
    Ответ написан
  • Как распарсить правильно URL?

    dollar
    @dollar
    Лучше отделить часть с параметрами, и затем разбить её на части вида key=value.
    Это будет универсальное решение.

    Попроще будет сделать ровно то, что вы запросили: проверить "a" сразу после знака вопроса:
    var text = `<a [routerLink]="['/dashboard/micebot/?a=serv11111121']">/micebot</a>`;
    var m = text.match(/\?a=([a-z1-5]*)/);
    if (m) {
      let a = m[1];
      console.log('"a" существует и равно ', a);
      if (a.length == 12) console.log('Длина "a" ровно 12, не больше');
    }
    Ответ написан
  • Как отсортировать массив в обратном порядке?

    dollar
    @dollar
    Можно просто через цикл с обращением по индексам в обратном порядке.
    for (let i = arrayWords.length-1; i >= 0; i--) {
      let n = arrayWords[i];
      //..............
    }

    Кстати, а почему вы в такой ситуации использовали map вместо forEach?
    Ответ написан
  • Есть ли простой способ найти конкретный элемент, если кликаешь на другой элемент?

    dollar
    @dollar
    Да, есть.

    Эти элементы должны быть связаны по смыслу. Тогда и будет способ из обработчика к одному элементу работать с другим элементом. Например, у них должна быть родительская связь. Или один должен следовать за другим. Или во время создания обработчика нужно передать в него индекс нужного элемента и т.д. Способов много. А самый элегантный зависит от конкретной задачи.

    Конкретно ваш код можно упростить, как минимум, до такого:
    Код
    let d = document, card = d.querySelectorAll(".card");
    var current = null;
    
    d.querySelectorAll(".btn").forEach(item => item.addEventListener("click", (e) => rotateCard(e)));
    
    function rotateCard(e) {
    	// Is there another way to find the item?
    	current = e.target.parentElement.parentElement;
    	current.style.transform = 'scale(2)';
    }

    Или можно учесть, что количество и порядок индексов одинаковый, и привязаться к нему. Тогда получится это:
    Код
    let d = document, card = d.querySelectorAll(".card");
    var current = null;
    
    d.querySelectorAll(".btn").forEach((item,j) => item.addEventListener("click", () => rotateCard(j)));
    
    function rotateCard(idx) {
    	// Is there another way to find the item?
    	current = card[idx];
    	current.style.transform = 'scale(2)';
    }
    Ответ написан
  • Зачем писать tooltipElem = null;?

    dollar
    @dollar
    Это оптимизация.
    Визуально разницы нет, но под капотом работает чуть быстрее.

    Когда событий сотни и тысячи (в небольшой промежуток времени), то оптимизация даёт более ощутимую разницу. В любом случае, лучше сразу писать правильно, чтобы потом не переписывать.
    Ответ написан
  • JavaScript или Python - на чем проще написать игру?

    dollar
    @dollar
    Оба варианта так себе.
    Потому что это как бы не совсем игровые языки, не смотря на то, что при желании игру написать всё-таки можно на любом из них.

    На ум приходят два популярных хороших движка:
    1. Godot - там как бы Python, но не он. Там свой скриптовой язык, очень похожий на Python. Проблема здесь в том, что если буквально прикручивать Python, то это повлечет накладные расходы производительности. Так что если не хотите учить новый язык (а зря), то попробуйте Godot - сам движок учить всё равно придётся.
    2. Unity - там как бы был JavaScript, и в целом даже ещё есть. Но разработчики этого движка давно поняли, что это бесперспективняк, и стараются всячески уйти от поддержки Javascript. Рано или поздно они её выпилят в пользу C#, который гораздо лучше для игр. Да и то там, как и в случае с Godot, не совсем Javascript, а очень похожий язык, который в свое время нарекли Unityscript.

    Таким образом, C# - лучший выбор.

    Ещё можно рассмотреть Lua, как вариант, он идеально подходит для описания игровой логики и прост в освоении. Но движки с поддержкой Lua пока что уступают вышеперечисленным. Проще взять тот же Unity и прикрутить к нему MoonSharp, например, чтобы иметь возможность использовать Lua. Но только если это действительно нужно - например, для поддержки модификаций.
    Ответ написан
  • Почему в данном регулярном выражении ленивый квантификатор не учитывает кавычку?

    dollar
    @dollar
    let str = '...<a href="link1" class="wrong">... <p style="" class="doc">...';
    let regexp = /<a href="[^"]*?" class="doc">/g;
    alert( str.match(regexp) );
    Ответ написан
  • Как отфильтровать массив объектов в объекте?

    dollar
    @dollar
    for (let year in data) {
    	let cache = {};
    	data[year] = data[year].filter(e=>{
    		if (cache[e.number]) return false;
    		return cache[e.number] = true;
    	});
    }

    Точно не знаю, что для вас значит слово "красиво". Если это значит в одну строчку, то мне кажется, что красота здесь является спорным моментом. Лично я под красотой понимаю, прежде всего, понятный код (для тех, кто с ним не знаком). А это в первую очередь означает наличие комментариев или хотя бы осмысленное именование. И для простых примеров как-то странно эту красоту наводить.

    Ну а по скорости всё зависит от алгоритма и акцента на использовании нативных функций. Выбор алгоритма, в свою очередь, зависит от многих факторов, которые в вашем вопросе не обозначены. Так что привожу просто наиболее очевидный для меня алгоритм.
    Ответ написан
  • Почему i = undefiend. В Функции условие if, в условии цикл for?

    dollar
    @dollar
    Потому что someLength меньше, чем num.
    Таким образом, цикл начинается с i = num, но не проходит первую проверку на i <= someLength, в итоге в цикле ноль итераций, в результате которых в массив ничего не добавляется.

    При этом i не равно undefined, оно равно именно num, но только в пределах цикла, который закончился сразу после того, как начался. А затем переменная i перестает существовать с точки зрения языка.

    К слову, если сделать someArr.push(undefined), то длина массива изменится. Так что в отсутствии работы цикла легко убедиться, проверив, что someArr.length === 0
    Ответ написан
  • Как найти баланс чисел в массиве?

    dollar
    @dollar
    Алгоритм такой. Все элементы помещаем в одну кучу (массив). Сортируем по убыванию. Дальше начинаем раскидывать по двум новым массивам. Параллельно считаем сумму каждого массива. Таким образом, раскладываем сначала большие числа, потом всё меньше и меньше. Каждый раз кладём новое число в тот массив, где сумма меньше.

    Очевидно, что последними будут идти самые маленькие числа, которые будут старательно минимизировать разницу в суммах. Доказать, что в итоге разница будет минимальна, я не могу (лень), но интуиция подсказывает, что это будет так.


    UPD:
    Такой алгоритм полного перебора
    function balance(arr1, arr2) {
      let all = arr1.concat(arr2);
    	//all.sort((a, b) => a - b); //Для исключения одинаковых.
    	let all_sum = all.reduce((a,b)=>a+b,0);
    	let len = all.length;
    	let cnt = Math.floor(len * 0.5);
    	let arr_result = new Array(cnt); //Массив выбранных индексов
    	let idx_begin = 0; //Начальная глубина перебора (индекс в arr_result)
    	let sum_begin = 0; //Начальная сумма частично перебранных элементов
    	
    	if (cnt === len * 0.5) { //Оптимизация
    		arr_result[0] = 0;
    		idx_begin = 1;
    		sum_begin = all[0];
    	}
    	
    	let min_diff = all_sum; //Присваиваем какое-то заведомо большое число.
    	let arr_answer; //Итоговый ответ
    	
    	//Проверяем следующий уровень глубины
    	//idx - глубина, sum - сумма всех элементов до этого
    	function check(idx, sum) { 
    		if (idx === cnt) { //Конец перебора. Проверяем, подходит ли.
    			let diff = Math.abs((all_sum - sum) - sum);
    			if (diff < min_diff) { //Подходит
    				min_diff = diff; //Запоминаем новый лучший результат.
    				arr_answer = arr_result.slice(); //Копируем
    			}
    			return;
    		}
    		//Иначе идем дальше вглубь на следующий уровень.
    		let start = idx === 0 ? 0 : arr_result[idx-1] + 1;
    		let max = len - cnt + idx;
    		for(let i = start; i <= max; i++){ //Ключевой цикл алгоритма
    			//if (i > start && all[i] === all[i-1]) continue;
    			arr_result[idx] = i;
    			check(idx+1, sum+all[i]); //Рекурсия
    		}
    	}
    	check(idx_begin,sum_begin); //Начать перебор. Поехали!
    	
    	arr1 = [];
    	arr2 = [];
    	
    	//Фасуем полученный ответ по массивам уже в виде значений.
    	let j = 0;
    	all.forEach((e,i)=>{
    		if (i === arr_answer[j]) {
    			arr1.push(e);
    			j++;
    		} else arr2.push(e);
    	});
    	
    	return {
    		arr1: arr1,
    		arr2: arr2,
    		sum1: arr1.reduce((a,b)=>a+b,0),
    		sum2: arr2.reduce((a,b)=>a+b,0),
    	}
    }
    
    var arr1 = [10, 300, 25, 75];
    var arr2 = [50, 125, 500, 10];
    balance(arr1, arr2);
    Ответ написан
  • Можно ли с помощью js удалить атрибут в элементе img?

    dollar
    @dollar
    Можно. Почему нет?
    spoiler
    Поиск не помог что ли? Или было лень искать? хм
    Ответ написан
  • Как эффективно выбирать каждый n элемент массива?

    dollar
    @dollar
    Эффективно - только через создание второго индексного массива. При этом, очевидно, проигрыш по оперативной памяти, но не архи большой. Объекты передаются по ссылке, и строки примерно до 12 символов - тоже по ссылке.
    var arr = [1,2,3,4,5,6,7,8,9,10,11,12]; //Исходный массив
    //Формируем вспомогательный индексный массив
    var i = 0;
    var every_5 = arr.filter(e => (++i) % 5 === 0); 
    //Проверяем
    every_5[0]; //Пятый элемент
    every_5[1]; //Десятый элемент
    Ответ написан
  • Что означает return function?

    dollar
    @dollar
    Дело в том, что функция в языке JavaScript - это объект, то есть она является значением. Её можно запихнуть в переменную. А потом эту переменную можно вызывать, как функцию.

    Пример:
    var f = function() { alert(123) }; //записали в переменную f целую функцию.
    f(); //вызвали функцию в переменной.

    Можно даже пойти дальше по этой логике. Ведь alert - это тоже функция.
    var f = alert;
    f(123);

    В общем, надеюсь, логика понятна. Что касается вашего кода, то в нем из названия функции makeCounter очевидно, что она создаёт счетчик, то есть создает то, что умеет считать. То есть создает функцию. Вот и получается, что нужно вернуть функцию. Записать это можно по-разному, в том числе и в одну строчку, которая начинается с return function.

    Ниже в строке:
    let counter = makeCounter();
    Мы как раз создаём эту функцию. То есть функция помещается в переменную counter. И чтобы это произошло, функция makeCounter должна вернуть функцию в качестве значения. Это и происходит.
    Ответ написан
  • Почему когда я использую set для добавления в массив, выдает ошибку?

    dollar
    @dollar
    Причины разные могут быть.
    Например, где-то в коде у вас что-то типа такого:
    function Map(){}

    Можете сами убедиться, запустив в консоли данный код:
    Код
    var data = new Map();
    var get = "key1";
    data.set(get, 1);
    function Map(){}

    Или же можно так испортить:
    Код
    Map.prototype.set = 123;
    var data = new Map();
    var get = "key1";
    data.set(get, 1);

    В общем, ошибку искать нужно не в приведенном вами коде, а за его пределами.
    Ответ написан