Pull to refresh

Comments 230

Зачем вы в некоторых примерах в зависимости от выполнения условия возвращаете из функции булево значение, если можно сразу вернуть из функции условие?

вернуть из функции условие
Хм, это как? Вы имели в виду вернуть другую функцию?
Я имел ввиду, что например вместо
arr.sort(function (a, b) {
  if (a.time - b.time < 0) {
        return false;
      } else {
        return true;
      }
});


Лучше сделать так
arr.sort((a,b) => {
  return !(a.time - b.time < 0);
})
Довольно часто первый вариант кода — очевидней.

Довольно часто это когда? Можно пример когда это будет очевидней?

Более очевидный вариант
bool IsBukva(char symbol)
{
switch(symbol)
{
case'a':return 1;break;
case'b':return 1;break;
case'c':return 1;break;
case'd':return 1;break;
case'e':return 1;break;
case'f':return 1;break;
case'g':return 1;break;
case'h':return 1;break;
case'i':return 1;break;
case'j':return 1;break;
case'k':return 1;break;
case'l':return 1;break;
case'm':return 1;break;
case'n':return 1;break;
case'o':return 1;break;
case'p':return 1;break;
case'q':return 1;break;
case'r':return 1;break;
case's':return 1;break;
case't':return 1;break;
case'u':return 1;break;
case'v':return 1;break;
case'w':return 1;break;
case'x':return 1;break;
case'y':return 1;break;
case'z':return 1;break;
case'A':return 1;break;
case'B':return 1;break;
case'C':return 1;break;
case'D':return 1;break;
case'E':return 1;break;
case'F':return 1;break;
case'G':return 1;break;
case'H':return 1;break;
case'I':return 1;break;
case'J':return 1;break;
case'K':return 1;break;
case'L':return 1;break;
case'M':return 1;break;
case'N':return 1;break;
case'O':return 1;break;
case'P':return 1;break;
case'Q':return 1;break;
case'R':return 1;break;
case'S':return 1;break;
case'T':return 1;break;
case'U':return 1;break;
case'V':return 1;break;
case'W':return 1;break;
case'X':return 1;break;
case'Y':return 1;break;
case'Z':return 1;break;
default:return 0;
}
}


www.govnokod.ru/212
гы-гы… напомнило вывод строки в лабе у одногруппника
Скрытый текст
for(int i=0; i<str_len; i++)
{
   if(str[i] == 'a')
   {
        cout<<"a";
    }
   if(str[i] == 'b')
   {
        cout<<"b";
    }
    ....
}
 

if ((a == b).ToString().Length > 4)…
переведите на любой язык, который нравится.
wut???
Это хоть на каком-то языке является валидным кодом?
UFO just landed and posted this here
UFO just landed and posted this here
А что ему может помешать быть валидным кодом?
Как-то сразу не подумал что булевое значение может быть объектом. Слишком привык на сишке писать.
C#, Javascript, Python — любое значение есть объект.
UFO just landed and posted this here
Долго думал, что же не так с этим кодом. Потом понял — отступов не хватает.
Или даже
arr.sort((a, b) => {
  return a.time - b.time >= 0;
})
Или даже так :)
arr.sort((a, b) => a.time - b.time >= 0);
А слона не приметили…
arr.sort((a, b) => a.time - b.time)
А вот так делать нельзя.
Внезапно
>> [0, Number.MIN_VALUE].sort((a, b) => a - b)
Array [ 0, 5e-324 ]
А что не так с массивом [ 0, 5e-324 ]?
Как минимум то, что он отсортирован по убыванию, тогда как компаратор предполагает обратное.
Вообще-то 5e-324 — это положительное число…
Таки да, был неправ при выборе элементов массива.

[1<<31, 1].sort((x, y) => x-y)
И опять все работает…

> [1<<31, 1].sort((x, y) => x-y)
< (2) [-2147483648, 1]
Сдаюсь. Видимо, действительно, javascript не подвержен переполнению.
Поправка: не подвержен переполнению при выполнении арифметических операций. Или, еще точнее, арифметическое переполнение не приводит к некорректному знаку:

> 1e200 * 1e200
< Infinity

А вот при выполнении побитовых операций переполнение еще как возможно:

> 1 << 31
< -2147483648

Кстати, можете попытаться найти ошибки кинув в исходный массив несколько Infinity — их вычитание даст NaN у которого знак не определен. Или можно сразу NaN в массив положить и посмотреть что будет. Но тут результат может отличаться в разных браузерах.

UFO just landed and posted this here
Да, спасибо, не доглядела. Действительно, местами можно было короче.

Треш, угар и содомия прости господи… Ну давайте уже давать людям нормальные тестовые задания на пару суток. Чтобы погуглить и подумать время было. А не эти все O-два-эН и бинарные деревья рисовать гуашью. Дурака всегда будет видно по явной копипасте, а умный даже если скопипастит, то это будет уместно.

Всякий ли разработчик захочет тратить пару суток на решение «нормального» тестового задания? А если учесть, что он в поисках, и может рассматривать несколько вакансий?

Это от разработчика зависит. Если он хочет на работе бинарные деревья рисовать то это его проблемы. По хорошему тестовому во первых понятно что разработчик из себя представляет, во вторых разработчик сразу для себя поймёт интересен ли ему стек с которым ему предстоит работать.

Всякий ли разработчик захочет тратить пару суток на решение «нормального» тестового задания?

А какая, собственно, разница? Предложение на IT рынке труда сейчас очень сильно превышает спрос, этот не захочет — на его место будет десяток других, которые захотят.

Вы на каком-то очень странном рынке IT живете. У меня все наоборот.
Удачи вам, держитесь.

Вы на каком-то очень странном рынке IT живете. У меня все наоборот.

На вполне себе обычном. Есть ведь статистика по динамике зарплат (рост которых в IT отстает от других отраслей) и по соотношению количества вакансий/резюме (каковое планомерно сдвигается в сторону резюме). А вы просто продолжаете жить в ~2005.

UFO just landed and posted this here
Ну и потом Россия далеко не единственная страна где нужны айтишники :)

Я про мир говорю. Россия, как водится, слегка отстает от мировых тенденций :)

UFO just landed and posted this here

Это для джунов или мидлов? Джунов как мне показалось, хватает, львиная доля всех резюме как раз от них. А вот мидлов и выше хотят забрать себе многие, т.к. их катастрофически не хватает, особенно на фоне кучи джунов. Хотя и среди джунов нет как таковых джунов.

UFO just landed and posted this here

А что у вас за ниша? Web, Mobile, Desktop, Embedded? Джуны сейчас все в веб лезут.

UFO just landed and posted this here
Ну вот я сейчас в Германии в городе-миллионике с наличием индустрии, хорошими зарплатами и своими университетами. Айтишников не хватает катастрофически. Причём всех: программистов, админов и даже тестеров.

На рынке всегда не хватает товара, потому что когда его хватает — цены начинают падать, пока его опять не будет нехватать. По-этому ощущения от того что "открыты вакансии, нет специалистов" — это не более чем ощущения, точно так же не хватает абсолютно любых специалистов в абсолютно любой области (если, конечно, мы не говорим о какой-то исключительной ситуации, когда в силу определенных причин вроде технического прогресса сотни тысяч человек оказываются выброшены на мороз).


Если бы в IT-индустрии была бы действительная нехватка специалистов, то это нашло бы отражение в ценах на труд IT-шников — средние зарплаты в отрасли росли бы с опережающими темпами, и это единственный объективный показатель нехватки специалистов на рынке. Мы этого не наблюдаем. И это если речь о мидлах/сениорах, джуны же скоро вообще будут готовы работать за еду опыт.


У нас на фирме постоянно открытые вакансии и так у большинства фирм в городе. С другой стороны я 3-4 раза в месяц получаю из различных источников «ненавязчивые предложения» сменить работу.

А это связано не с нехваткой айтишников, а с их огромной текучкой (по сравнению с другими отраслями).

UFO just landed and posted this here
Зарплаты до бесконечности расти тоже не могут. Потому что с какого-то момента становятся экономически невыгодными

Если рост зарплат экономически невыгоден, то значит рынок достиг равновесия. То есть, любая добавочная рабочая сила приведет к избытку на рынке труда и падению зарплат.


И здесь зарплаты у айтишников достаточно высокие если сравнивать их со многими другими професиями, требующими аналогичного образования.

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


Я не знаю о каких стране-городе говорите вы, но у нас даже azubis получают доплаты с которыми им вполне себе комфортно живётся.

Не знаю, про какую страну-город вы, но я о средне-мировой температуре по больнице. Требования к джунам последние годы стремительно растут (то, что сейчас иногда требуют от джунов, лет 10 назад тянуло на крепкого мидла), а зарплаты отстают.

UFO just landed and posted this here
UFO just landed and posted this here
Ссылки на статистику — это ОК. Уточните, вы про какие страны говорите, про все IT вообще, включая «операторов ЭВМ» или про какие-то конкретные специальности? И можете продемонстрировать эту самую статистику?
Просто наблюдаемая вокруг меня действительность ровно обратная, в моей области и всех смежных зарплаты растут хорошо, даже отлично, спрос сильно опережает предложение.

Вы вроде упомянули «про мир». Ну я разработчик на golang — и следуя статистике stackoverflow это один из наиболее высокооплачиваемых языков. Прирост зарплат с 2005 года был с 0 до 110K USD по медиане.
UFO just landed and posted this here
На мой взгляд как-раз таки айтишников очень сильно не хватает.

По сравнению с кем? Хотите сказать, что найти хорошего айтишника проще, чем хорошего экономиста? Менеджера? Слесаря?

UFO just landed and posted this here
:) Возьмите, уже не плохо обучен, готов учиться дальше и стремиться к большему:)
А верстаете тоже с синтаксическими ошибками в словах? :P

Я развиваю в себе навыки правильного и безошибочного написания) но все сразу!

Вы же не просто так сказали, то может где-то подробней обсудим? Вдруг я вас заинтересую)

А если за тестовое заплатить? :)

Хорошее собеседование как по мне — должно напоминать экзамен: «билет это только повод начать разговор»… =)

А что делать, если я пишу код лучше чем говорю? Вот этот вопрос


Как применяются скругленные углы для элементов и стили для текста(шрифт, тип шрифта, цветащте и тд)?
Единственное, что я смогу ответить, это
  • А что конкретно вас интересует?

Я знаю хорошо какие приоритеты у каких селекторов, что и куда применяется, и знаю это уже на уровне рефлексов. Если я сверстал больше десятка макетов, разве мне уже это не понятно? Да даже если я не знаю какой-то момент, во время работы я легко могу проверить это в инструментах разработчика хрома. Мы же не пишем код на бумажке, в изоляции от интернета и крутых инструментов. А вот задание на дом как раз в этом плане лучше, покажет, что кандидат умеет искать ответы на вопросы.

Умение говорить — одно из самых необходимых качеств для разработчика. С помощью коммуникативных навыков многие проблемы решаются намного быстрее, а некоторые мгновенно.

Одно дело, говорить по делу, обсуждать проект. Другое дело, лить воду на совершенно ненужные вопросы. Я чаще сталкиваюсь, что человек умеет очень все красиво рассказать, а когда дело доходит да кода, он теряется.

О, это я! Не знаю, в негативном или позитивном ключе вы рассуждаете, но


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


Если начинались тестовые задания… Пустота, в голове ни одной мысли.
Пару раз попадал так, что тестовые задания были, но и принимающие были адекватны и позволяли описать алгоритм в процессе разговора — все сразу становилось на свои места.
(в большинстве случаев это скорее Ад "нет, вам нельзя гуглить")


Не знаю почему так. В разговорах — камень, ни испуга, ни волнения.
А пишешь код и даже если у себя на ноутбуке, будто он не свой, а только украл у рекрутера и только думаешь, как свалить пока не заметили. Простейшие термины и приемы, скажем — рекурсия становятся нерешаемыми.


Так и не справился с проблемой, слишком большой стресс оставался после провалов, в итоге немного сменил должность и в принципе, она мне подходит больше. Но осадок остался.

Тестовые задания на пару суток могут расцениваться многими кандидатами как попытка реализовать что-то за бесплатно силами соискателя с последующим «извините, вы нам не подходите».
Таких контор полно, а нарисуйте логотип или интерфейс / кнопочки / панельки — а потом какие деньги?
Ну давайте уже давать людям нормальные тестовые задания на пару суток

Ну вот допустим, пригласили меня на 5 собеседований — на каждом дали по заданию на двое суток. Две недели сидеть все делать, только чтобы получить шанс устроиться в одну из компаний?

По-моему как раз таки гораздо удобнее прийти на собеседование — и там на месте все решить, чем брать «домашнее задание»

По своему опыту — когда дают тестовое задание — в 90% случаев просто забиваю на него и продолжаю собеседоваться в других компаниях.

Компания, которой вы неинтересны, не даст вам тестовое задание. Максимум — "мы вам перезвоним". Для компаний, которые вам неинтересны, по результатам собеседования, вы не будете выполнять тестовые задания. Полный паритет и "благорастворение воздухов".
Первое собеседование не должно быть экзаменом. Оно должно быть соглашением о намерениях. Впрочем, это всего лишь мое IMHO.

Полный паритет и «благорастворение воздухов».

Не исключаю, что такое случается, но например мой опыт, когда я год назад искал работу — я прошел 8-10 собеседований. Где-то половина компаний была мне не интересна. Т.е. по итогу у меня на руках было 4 джоб офера, из которых было достаточно трудно выбрать т.к. даже после нескольких собеседований и кучи разговоров по скайпу трудно понять какая компания лучше (а предложения у всех ± одинаковые)

Ни в одной из компаний, кроме Яндекса, тестовое задание мне не давали. Все определялось как-раз решением простых задачек на знание языка (без всяких сортировок) и разговорами с тех лидами.
В Яндексе задание было буквально на пару часов и сама задача была очень простой, думаю смотрели скорее качество кода, напишу ли тесты и т.п. (если что, тестовое задание я прошел, но потом меня все-равно туда не взяли :) )

ПС
У меня тоже основной ЯП — JavaScript
Задача с собеседования, которая больше всего мне запомнилась — попросили написать свою реализацию полифила функции `bind`
Это, на мой взгляд, сразу проверяет знание многих аспектов языка.
А такие вещи как умение пользоваться гитом, фрэймворком и т.п. довольно легко проверяются просто в диалоге.

Кто сказал, что из js нельзя менять значения before и after?
Для задач, выходящих за пределы возможностей инлайна, существует document.styleSheets

Можно даже просто создать тег style, записать туда всё, что надо, и вставить на страницу. А там вполне можно перекрыть before/after.
А не расскажите подробнее, как из атрибута style добраться до before/after? Или ссылку на почитать? Была бы очень благодарна, а то хоть и верстаю много, но не знаю как такое реализовать
Спасибо, примерно таким подходом как вы показали я и пользуюсь.
Но @Keten пишет о другом (я очень вдумчиво перечитала комментарий и поняла предлагаемый способ)
Предлагается в скрипте создать тег с нужными стилями и встроить его на страницу (при не вдумчивом прочтении, я упустила, что речь идет о теге, а не об атрибуте)
Все равно, приведенный мной способ, можно назвать с большой натяжкой управлением псевдоэлементами js-м. Скорее финт ушами.
46. Что будет если задать margin: -10px; -> Сдвинется вверх и влево на своих соседей

Не факт. Зависит от того, какое значение display. Инлайновые элементы таки могут не поехать вверх.

48. Моему коллеге на должность php-разраба, предложили такую
Есть два блока, второй скрытый, если в первом нет дочерних элементов, то показать второй.

Скрипты? А может быть...
.b {
    display: none;
}

.a:empty + .b {
    display: block;
}

Не факт. Зависит от того, какое значение display.

Да, здесь я виновата, не корректно пересказала. Там речь шла о div с позиционированием static

Скрипты? А может быть...

С его слов надо было с использованием нативного js.
27. ...overflow: hidden — полностью скрывает элемент, он не видим и не занимает место на странице. javascript не может получить ни width, height.

Тут тоже что-то недосказано? Просто так от добавления overflow: hidden элемент никуда не исчезнет.
никогда не делай на js то, что можно сделать на css
Тоже подумал про вариант с псевдоселектором :empty первым делом, жаль только он не сработает если есть хотя бы пробел или перенос строки в тэге
в задаче стоит условие «нет потомков», при пробеле или переносе строки в потомках окажется текстовая нода
Вопросы конечено интересные, если просто, чтобы подумать под настроение. Но такие интервью конкретно уже надоели.
Вариант с
function getStr() {
	return [].slice.call(arguments, 1).join(arguments[0])
}

красивый, безусловно, но что это говорит о кандидате, если он это решение выдал с пол-пинка или наоборот решил «в лоб»?
красивый, безусловно, но что это говорит о кандидате

Наверно по принципу: «Если решил такое, то и с другим справится». Вообще, я скучаю по тем временам, когда вопросы были типа: «Чем function Declaration отличается от Expression».
Ну если работодатель готов отсеивать много кандидатов, которые хорошо бы справлялись с реальной работой и брать по принципу если уж это смог — это его личное дело.
Ну если работодатель готов отсеивать

Я тоже считаю, что такой тип вопросов не показатель. Как-то меня попросили набрать вопросов для собеса кандидатов в один проект mail. Я с энтузиазмом предложила те, что у меня были из яндекса + ряд в том же духе, для подготовки к нему. Но тим лид отверг этот принцип(просто в яндексе любят вопросы про сортировки, очереди, деревья и другие достаточно специфичные, не часто используемые на практике вещи)
Такие вещи легко гуглятся, при возникновении необходимости.
Если такие штуки стоит давать на интервью, то наверное лучше в виде задач, чтобы за компом и не стояли над душой.
Тогда это приближённо к реальной работе и можно увидеть как человек справляется с такими вещами по мере необходимости.

Я вот не помню даже по названиям все общеизвестные алгоритмы сортировки, кроме пузырька самого, который на слуху. И если надо будет в реальной жизни использовать сортировку вместо Array.sort() я полезу гуглить естественно и найду, и сделаю. Но навскидку не помню и не понимаю зачем это помнить.
function getStr(separator, ...args) { 
    return args.join(separator);
}
Тогда уже так:
const getStr = (separator, ...args) => args.join(separator)
Как вариант, но я сознательно не стал использовать стрелочную функцию, т.к. у неё нет имени. Это плохо сказывается на стектрейсах.
Считаю, что стрелочные функции надо использовать только тогда, когда они создаются и используются в одном и том же месте. Хотя это достаточно спорное мнение.
Вроде уже браузеры научились выводить имя переменной:
Рискну огрести ещё минусов, но если того, кто поставил минус не затруднит объяснить свою позицию — буду благодарен…
1 минус — не обращайте внимания. Кто-то даже промахнуться случайно мог
Насчёт промахнуться не подумал. Просто так интересно стало «аж кюшать не могу».
Извините, если я неправильно понял, но мне кажется в 13 происходит что-то странное. Я плохо знаю JS, но, кажется, вы считаете сумму кодов символов для каждого слова? Если так, то это неверный подход. Кроме того, выглядит так, что для (arr.length-2) слов вы считаете эту сумму дважды.

Есть несколько неверных ответов, к примеру
12 Колбек функции sort должен возвращать число, а не булево значение, это важно. Контр-пример:


[8,4,9,7,6,5,4,3,2,1,0].sort((a,b) => a > b); // [5,0,1,2,3,4,4,6,7,8,9] (в хроме)

13 Сумма кодов символов не сработает, пример


sameWords(['lnt', 'tok', 'okt']) // true

примитивное решение с сортировкой
function sameWords(arr) {
    var firstSorted = arr[0].split('').sort().join('');

    for (var i = 1; i < arr.length; i++) {
        var sorted = arr[i].split('').sort().join('');
        if (firstSorted !== sorted) return false;
    }

    return true;
}

38 Вариант с eval не сработает вот тут: {{}}

И сортировка провалится на


sameWords(['tokkkkkk', 'okttttttttttt'])

В нормальных языках это решается через структуру данных множество, или ее костыльную эмуляцию через мап или хэшмап. В js же сейчас по слухам тянут все на свете, "да косу еще впридачу, да лопату с мясорубкой" (С) А множества до сих пор не притянули?

И сортировка провалится на

Это ваши домыслы. Исходя из первоначальных условий задачи, вариант с сортировкой — один из простых, что приходит в голову, лаконичных и решающих задачу. Желание все усложнять на ровном месте — не есть хорошо. Особенно на интервью. Рискуете потратить время, не успеть решить нужную задачу в попытках порешать не ту, которую требовалось. В реальной жизни все ровно также.

Если интервьювер попросит или кандидат попросит уточнений, то можно порешать и второй вариант.

В нормальных языках это решается через структуру данных множество

После этих слов видно, что с JS вы далеко на «Вы». В чем смысл было комментировать, если с языком плохо знакомы?
Вот новомодный вариант: [...(new Set('okttttttttttt'.split('')))].sort()
Вот old school: h = {}; 'okttttttttttt'.split('').forEach(function(x) { return h[x] = 1; }); Object.keys(h).sort()
И это далеко не все варианты как убрать дубликаты, но с фокусом на использованием «структуры данных множество».
После этих слов видно, что с JS вы далеко на «Вы». В чем смысл было комментировать, если с языком плохо знакомы?

Да, на Вы. Но все представленные задачки делятся условно на 2 класса — JS-специфичные и общеалгоритмические, допускающие решение на любом языке. Не вижу причин не комментировать вторые, даже если с языком на Вы. Особенно, если они в оригинале решены неправильно или неоптимально. Особенно, если я догадываюсь, что в JS все-таки есть множества, но о них никто не вспомнил при решении.

хилые там множества — я когда увидел в спецификации Set раскатал губу, решил, что будут всякие там пересечения, объединения и произведения множеств, а по факту сделали какую-то полумеру.

Формулировка задачи немного размыта, но судя по вот этим строчкам в решении это и требовалось


if (arr[i].length !== arr[i+1].length) {
        return false; 
Вариант 4 можно более лаконично описать)

function getStr(asterisk, ...rest) {
	return rest.join(asterisk);
}
UFO just landed and posted this here
Нет, в таких случаях напрашивается return и условие. Без лишних операторов.
if (...) { 
   return true + false == true;
} else {
   return true + true == true;
}
Как вы бы сделали отказоустойчивый сайт?

Ну вот и как на это отвечать? На ум приходит только что-то типа: «Я бы сначала хорошо всё обдумал, а потом закодил.»

validBraces('(})') вернёт неправильный ответ

Да чего далеко ходить, достаточно просто '}' или ')'. Хотя там формулировка странная, так-то эти варианты подпадают под «все скобки закрыты».
const validBraces = (s) => {
  const z = s.replace('()','').replace('[]','').replace('{}','');
  return z==s ? z=='' : validBraces(z); 
}
Отлично, квадратичное время работы на пустом месте… А еще вы забыли что первый параметр replace — это регулярка, и скобки там надо экранировать. Вы свой код вообще проверяли?
Вы не правы: скобки, заключённые в кавычки, являются именно строкой, а не регулярным выражением, так что экранировать ничего не нужно.

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

Обожаю комментаторов с Хабра ) Я и не знал что принимает реплейс — поэтому просто посмотрел в документацию:


The replace() method searches a string for a specified value, or a regular expression, and returns a new string where the specified values are replaced.
Note: If you are replacing a value (and not a regular expression), only the first instance of the value will be replaced. To replace all occurrences of a specified value, use the global (g) modifier

А алгоритму фиолетово — онли ферст инстанс или все сразу. И да, я проверял свой код. А вы, похоже — нет. Просто сразу кинулись писать опровержение, не удосужившись проверить. Второй комментатор из той же серии ) Да, будет замена только первого совпадения. Да это делает алгоритм работоспособным, и это очевидно любому.


А про квадратичность — преждевременная оптимизация сами знаете что )

Это хорошо что вы туда посмотрели. Потому что я просто знал что этот метод принимает — но знал неправильно. Самое смешное, что я ваш код запустил и увидел что он не работает, а теперь сижу и не могу вспомнить как же так хитро я его запускал :-)
То есть вы считаете, что функция, выполняющая по одной замене для каждого вида скобок, — самодостаточна?
Но они закрыты в неправильном порядке, так что правильной скобочной последовательностью ваш пример не является.
Тут вопрос в ТЗ.
С одной стороны о правильности порядка в ТЗ разговора не было.
А с другой стороны в данном примере:
"(qwerty)"

скобки закрыты, но функция работать не будет.

Поэтому я и не считаю ваш вариант действительно рабочим, однако признаю, что на собеседовании он прокатил бы и выглядел, как минимум, интересней варианта топикстартера)
выполняющая по одной замене для каждого вида скобок

Там не одна замена, она повторяется, пока не останется ничего, что можно заменить
То что там рекурсия — это видно. Я говорил о другом — выше примеры)

Вы демонстрировали полное невежество и непонимание (у Хабра все посты записаны), неоднократно садясь в лужу, а сейчас пытаетесь "сохранить лицо", хотя уже давно всем все понятно ) Можете минусовать, ибо похвалы от вас я бы стыдился )


ЗЫ про кота с буквами — ну децкий сат же.


const validBraces = (s) => {
  const go = (s) => {
    const z = s.replace('()','').replace('[]','').replace('{}','');
    return z==s ? z=='' : go(z);
    }
  return go(s.replace(/[a-zA-Z0-9éèêëùüàâöïç \n\r]/g,''));
}
За что минусовать? У вас есть мнение — я за вас рад, вполне)

Я правда не понял, когда это я неоднократно садился в лужу, если это первый пост в котором я отметился в комментах (у Хабра все посты записаны).
Да и конфликт только в треде с вами обнаружился.
Вы как-то близко всё к сердцу принимаете. Я написал комментарий, в котором защитил ваш код (в вопросе о регулярном выражении и стрингах) и позволил себе заметить, что функция всё равно неработоспособна, что позже оправдал глупостью самого ТЗ.

Где вы нашли невежество и непонимание? Почему похвала от меня — это стыдно? ХЗ)
Ну да и ладно, не обижайтесь)

А теперь исправьте алгоритм для общего случая :)


validBraces("[안{녕(하(세(요)!)~)~}~]")
Можно ведь удалять все, кроме кавычек. Или сперва найти только кавычка и потом работать с ними:

var getBraces = str => str.match(/[\[\]{}()]/g, '').join('')

getBraces("[안{녕(하(세(요)!)~)~}~]");

// =>

[{((()))}]


s.replace('()','').replace('[]','').replace('{}','');
Интересный подход. А сможете адаптировать, чтобы при наличии других валидных символов не ломалось?

validBraces('{ab(cd)ef}'); // true

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

Дело в том, что вы просто не знали, что я на этой задачке пол-собаки съел в свое время ))) Вот например еще один выставочный специально селекцированный кот для нее — для эстетов:


const validBraces = (s) => {
  var it = s[Symbol.iterator]();

  const f = (i, a) => {
    const b = it.next().value; 
    return !b ? i==0
           : '([{'.includes(b) ? f(i+1, b) && f(i, a)
           : ['()','[]','{}'].includes(a+b);     
  }
  return f (0, ' ');
}

ЗЫ я не собеседую программистов (собеседовал лет 15 назад), но такой кот


var sum = 0;

function getSum(obj) {
    sum += obj.valueNode;
    if (obj.next != null) {
        for (var i = 0; i < obj.next.length; i++) {
            getSum(obj.next[i]);
        }
    }

    return sum;
}

скорее сработал бы в минус кандидату, чем в плюс. Не говоря уже про ипические "иф тру ретурн тру элсе ретурн фалс", по которым уже проехались выше.

а не могли бы вы рассказать, что конкретно тут плохо?
Как минимум, неоправданное использование глобальной переменной.

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

Можно правильный вариант кода?
Хотя-бы так (чистая функция без побочных эффектов):
function getSum(obj) {
   if (obj.next == null) return obj.valueNode;
	
   var sum = obj.valueNode;
	
   for (var i = 0; i < obj.next.length; i++) {
      sum += getSum(obj.next[i]);
   }

   return sum;
}


Можно в более ФП-стиле:

const add = (a, b) => a + b;

function getSum(obj) {
   const childrenValue = (obj.next || [])
      .map(getSum)
      .reduce(add);
	
   return obj.valueNode + childrenValue;
}
для ФП стиля, нужно в reduce вторым аргументом передать 0, иначе на пустом массиве будет ошибка
Я ни разу не программист, но если бы был:
"… попап по центру…… что бы он прокручивался вместе со страницей..."
Если бы мне такое задание предложили я бы спросил серьёзно ли они собираются предлагать подобные задания или это исключительно для проверки знаний и если ответ был бы не в пользу знаний я бы молча встал и ушел.
*негодование*: Они бы ещё Infinite Scroll предложили продемонстрировать, и кнопку «Наверх» расположенную там куда обычно люди уводят мышку чтобы курсор не отвлекал.

Народ подскажите браузер который может такие попапы не скрывать, но делать не мешающими. Никогда не понимал логику производителей браузеров. Придумали стандарт который позволяет открывать новые окна — реализовали, народу не понравилась вечно лезящяя реклама — придумали предупреждение о всплывающих окнах (которое по умолчанию не работает если пользователь совершил клик). И как бы функция осталась и в тоже время не мешает (почти). Почему не реализовать подобное с попапами? Если браузер в котором можно было бы просто выключать определённые js возможности?
Попап — это не js возможность, это css возможность.
UFO just landed and posted this here
Меня тут недавно поймали на переменной в замыкании — codepen.io/Fen1kz/pen/KRvNYP

И ещё на утечке памяти при обработке асинхронных месседжей с вебсокетов. Так что я бы ещё в статью добавил какую-нибудь хитропридуманную задачу про утечки памяти.
Ваш случай лечится элементарной заменой
for (var i = 1; i <= 3; ++i)

на
for (let i = 1; i <= 3; ++i)
> лечится

Так это не баг, это задачка на собеседовании =/

И по-хорошему лечиться не должно даже с let, это просто транспиляторы делают

var _loop = function _loop(i) {
  document.getElementById('lol' + i).onclick = function () {
    return alert(i);
  };
};

for (var i = 1; i <= 3; ++i) {
  _loop(i);
}
Не обязательно транспиляторы. Современные браузеры тоже let понимают.
2018 год на дворе, все браузеры уже научились в let и const
Не все… Opera Mini все еще популярна
Ну в рунете у неё уже меньше процента, всё ж не популярна уже, так что можно смело заявлять, что все умеют)
Почему вы считаете что «умники с 2018 года» не могут объяснить что let создает новый лексический блок?
Потому что вы этого не сделали
А почему вы спrашиваете?
а вот объяснить что let в цикле в отличие от var создает новый лексический блок все так же не могут
Ну, допустим, не могут. И что?
Казалось бы, причём здесь мы, если за развитием языка последние три года не следили именно вы)
9. ресет стилей делается не для того что бы не делать каждый раз, а потому что в разных браузерах значения по умолчанию разные, раньше с этим была вообще беда.
38. Совсем велосипед, зачем перебирать все? Зачем считать совпадения? Все проще же:
function validBraces(str) {
	var st = [];
	return str.split('').every(function(br){
		var idx = '[{(]})'.indexOf(br);
		if(idx < 3){
			st.push(idx + 3);
			return true
		}
		return st.pop() == idx;
	}) && st.length == 0;
}

49. Забудьте про eval, вообще. Это дорого, и не хилый шанс выстрелить себе в ногу.

По поводу 38. Код из статьи корявый, но по виду, а не по сути. По сравнению с вашим, обладает двумя преимуществами.


Во-первых он не создаёт дополнительного массива. Это мелкая придирка, но чем длинее строка, тем непрятнее этот дополнительный массив.


Во-вторых, ваш код использует every там, где его семантически быть не должно. every делает проверку для каждого элемента массива, но гарантий, что это будет делаться последовательно — строго говоря не даёт. Поэтому цикл тут уместнее, чем лямбда.

На самом деле стандартом предписан вполне конкретный алгоритм, и в нем every вызывается ровно 1 раз для каждого элемента до первого ложного значения.


Хотя я тоже считаю что цикл тут уместнее.

Во-первых. В коде статьи создается массив arrOpenSymbols с ровно таким же предназначением и не меньшей размерностью во время работы. Я не знаю всех тонкостей работы интерпретаторов ECMAScript и их внутренних структур данных, но опыт подсказывает что хранить в этом массиве строки и их сравнение дороже чем тем же операции для чисел.

Во-вторых. every перебирает элементы именно последовательно от 0, и прекращается если результат для очередного элемента лож или достигнут конец. То есть «для каждого» только в худшем случае. Не измерял, и every действительно может оказаться хуже цикла, из за вызова коллбека в цикле, из за чего будет происходить дорогая смена контекста, но пример был направлен именно на то что не надо перебирать все, и такой код демонстрирует это лучше, правда только если вы знаете как работает every.

"Дополнительный массив" — это не st, а str.split('').

А, тут да, есть лишнее, согласен. У меня какая то своя не любовь в индексации строк как массивов именно в JS, наверное со времен когда с не латиницей было совсем туго, и длинна одной и той же строки в разных браузерах была разной, надо отучать себя.
Чтобы провести собеседование с разработчиком, не надо его заваливать тонкостями и головоломками. Достаточно с ним поговорить на профессиональные темы минуть пять. Когда сам озадачен актуальными вопросами, коллега с большой вероятностью либо сам с ними уже когда-либо сталкивался, либо может прямо в беседе проконсультировать.

Плюс, командная работа — это всегда совместимость между людьми. Если человек вам неприятен, с большой вероятностью это скажется и в работе отрицательно. Поэтому важно выбирать тех, с кем придется работать ежедневно. То что он знает в совершенстве какие-то темные стороны языка программирования — это дело совсем даже не десятого порядка важности.

Пробелы в каких-то знаниях — не недостаток. Мы сейчас живем в условиях, когда то, что было еще полгода назад, — уже мало актуально. Для веба это особенно актуально — тут все меняется так серьезно, что все приходится изучать с нуля. И на готовых проектах. Ни разу в моем опыте не было такого, чтобы лично я что-то специально заучивал наизусть и требовал или ожидал заучивания от других. Абсолютно всегда приходилось быстро вникать в то, что видишь впервые в жизни. И нет времени на тонкости. Понимание тонкостей приходит с опытом. И чем больше кругозор и опыт разработчика, тем с большей правдой он, даже не зная новую для себя вещь, сможет быстро догадаться о потенциальных проблемах. Потому что все компьютерные технологие построены на примерно одинаковых вещах, где есть типовые недостатки и подводные камни.

И такой подход я получил от своих преподавателей еще советской школы. Специалист — это не тот кто все знает, а кто знает где найти справочник или того, у кого можно проконсультироваться. И эти мои преподаватели делали прорывы в технологиях и науке.

А то что я вижу сейчас в собеседованиях — это стыд и позор. Набирают, такое ощущение, — лишь кодировщиков, кто бы очень быстро кодировал все, что им прикажут сверху. Раньше такая профессия была — Оператор ЭВМ. Очень похоже.

Если вы новичок в программировании, вам все-равно эти типовые головоломки ничего не дадут, хоть выучи наизусть, хоть месяцами сиди в интернете и штудируй курсы. А уж попытки вызубрить наизусть какие-нибудь популярные темы типа шаблонов проектирования или все классы стандартной библиотеки и вовсе тщетны. Через неделю все выветрится из головы.

Реальное обучение проходит напрямую в живом проекте, когда то что тебе нужо, находишь и применяешь. В этом деле через месяц уже станешь разбираться лучше абсолютного большинства тех, кто обучает на курсах. А если это станет твоей специализацией, так все тонкости раздобудешь и будешь в этих вопросах разбираться лучше чем большинство других программистов. Просто потому, что это тебе нужно и это твоя работа.

Если же ты уже опытный программист, все эти вопросы на собеседованиях раздражают. Если ваш собеседует живой человек, а не программа по отсеву программистов (бывает такая жесть — когда присылают ссылку на веб вопросник), он сразу оценивает тебя и переходит к твоему реальному уровню очень быстро. По крайней мере, у меня всегда было так. И меня брали с существенными пробелами в знаниях, потому что собеседующие были адекватными. Им нужен был не заучка и энциклопедист, а инженер.

Еще бывает такая вещь, как синдром вахтера. Когда HR работник лучше самого работодателя знает, кого надо нанять: высчитывает его психологическую карту, чуть ли не как на ТАРО строит твой почти гороскоп, загружая свою голову барахлом из псевдо-научных психологических верований. И занимается он такой фигней, искренне веря, что тем самым делает благое дело, не понимая, что его задача — поиск и первичный отсев тех, кто точно не подойдет. Не больше. Нормально собеседовать человека сможет прямой руководитель.

В-общем, фигня все эти задачки и попытки рыться в пробелах кандидатах. Прочитал я эти вопросы. В моем опыте абсолютное большинство указанных вопросов — то с чем программист скорей всего не столкнется. А если он чего-то подзабыл или не знает, ничего страшного — ему платят за то, чтобы он умел находить решения.

Лично мне коллеги-заучки не нужны.

Как быть, если вы заметили неадекватных собеседующих? Либо прямо про это им говорите либо молча уходите. Себе дороже терпеть этот бардак. Вам же с ними потом вместе работать. Но вы должны быть уверены в своих словах. Это не волшебная мантра, — вы должны готовы отстоять свои слова. Иначе не беритесь с кем-то спорить. Нет ничего смешнее человека, кто строит из себя крутого мачо, но на деле у него пшик. И не беритесь брать ответственность в тех вещах, где у вас немнного не хватает квалификации. Это ваша работа — уметь в условиях неизвестности решать трудные технические задачи. Мне такая тактика в свои годы позволила из только что окончившего ВУЗ птенца сразу перейти в разряд ключевых работников организации.

PS. Я профессиональный разработчик. Еще вживую видел перфокарты. Собеседовал несколько раз и сам принимал участие в собеседованиях. К сожалению, смотря на все это вокруг, становится очень грустно. Не потому что я что-то не знаю из того где лично меня «валили», а потому, что многие собеседующие и собеседуемые ничего не понимают в разработке — а на основе своих странных знаний о программировании принимают неверные решения.

Не писал никогда на хабр, но последние перлы на хабре касаемо собеседований не оставили меня в стороне.
Хотел написать подобное, но вы точно описали мои мысли, респект!

От себя ниже добавлю, что большинство вопросов, которые я прочитал в статье — никогда не понадобятся в реале на фронте. Больше 10 лет я работаю с JS. Когда вижу такие вопросы, задаю один вопрос — где у вас это применяется?

PS и еще, всегда умалял вопрос по поводу сортировки. Типа отсортируйте массив (конечно не используя sort) по каким-то критериям или алгоритмам. Ну серьезно, вы действительно на проектах не сортируете массивы с помощью sort? Если так, то это же глупо.
UFO just landed and posted this here
про сортировки, в большинстве случаев на вопрос о сортировке проходит: метод sort будет более читабельным и более быстрым, т.к. под капотом у него или qsort или ksort (в зависимости от движка)
однако, в бытность фрилансером-оутсорсером, собеседующие познакомили меня с сортировкой подсчетом, которая наиболее эффективна для больших массивов состоящих из небольшого набора возможных значений

к чему я это: если спрашивают какой-нибудь «пузырек» — это бред, но иногда у бизнеса могут быть специфические данные, задав вопрос про сортировку подсчетом и объяснив предпочитаемое решение, собеседующие заполнили мой пробел в знаниях критичный для предстоящей задачи
Еще бывает такая вещь, как синдром вахтера. Когда HR работник лучше самого работодателя знает, кого надо нанять: высчитывает его психологическую карту, чуть ли не как на ТАРО строит твой почти гороскоп, загружая свою голову барахлом из псевдо-научных психологических верований. И занимается он такой фигней, искренне веря, что тем самым делает благое дело, не понимая, что его задача — поиск и первичный отсев тех, кто точно не подойдет.

А статья-то тут как тут: https://habr.com/post/354696. Выбираем претендента по оформлению резюме)

Серьезная опечатка. Исправить в тексте не могу, нет полномочий. В конце следует читать так: И не беритесь бойтесь брать ответственность.
Дело в том, что всегда работаешь на свое развитие. Поэтому выход из своей зоны комфорта необходим. И это основное, что нужно в инженерных специальностях. Мы работаем с творчеством и неизвестностью. Здесь нужен результат.

С каких это пор сумма арифметической прогрессии (задача 23) равна (n + 1) / (n / 2)?
Ну и как тут уже заметили, большинство примеров кода очень "не очень".

Забавная история с палиндромом, особенно если учитывать, что первый вариант не работает.
>> isPalindrom1(«12313331»)
<< true
>> isPalindrom(«12313331»)
<< false
39. Напишите код, который при клике на любой div внутри root будет выводить в консоль его id.

<div id="root" style="background: red;">
    root
    <span id="id1" style="background: lightblue;">id1</span>
    <div id="id2" style="background: green;">
        id2
        <div id="id3" style="background: yellow;">id3</div>
    </div>
</div>



Ваша функция в ответе не совсем корректна.
1) при клике по span она так же вернет его ID.
2) клик по root — так же не должен отрабатывать так как он, согласно условию, не находится внутри самого себя

3) event.stopPropogation(); по условию делать не требовалось

Автору
Не являюсь знатоком JavaScript, поэтому не берусь оценивать вопросы и ваши ответы. Но я здесь увидел ваше искреннее желание программировать, разбираться во всех тонкостях и учиться. Поэтому они зря вас не взяли — знание не предполагает желание учиться. Найдут себе всезнайку, будет он пальцы гнуть и никого не слушать.
В задаче 13 у вас неверное решение, попробуйте например на arr = ['kot', 'sol', 'okt']
27. Чем opacity отличается от visible: hidden и что это такое, отличие от overflow: hidden?
Ответ:
overflow: hidden — полностью скрывает элемент, он не видим и не занимает место на странице. javascript не может получить ни width, height.

Элемент со стилями visible: hidden так же занимает место, не видим. Но в отличие от элемента с opacity, js-события на нем не срабатывают.

visible: hidden — нет такого свойства, есть visibility + дочернему можно дать visibility: visible и он станет видимым в скрытом родителе, с opacity такого не провернуть =)
overflow: hidden — вообще из другой оперы. Обрезает контент, который вылазит за пределы блока + дополнительные скрытые эффекты типа «чистки» потока и др.
overflow: hidden — вообще из другой оперы
Да, автор перепутал overflow: hidden и display: none
«Кем вы видите себя через 5 лет?»
Когда-то меня бесил этот вопрос, но потом я нашёл на него ответ и хочу поделится.
1. Если вас сейчас всё устраивает, вам нравится делать\работать то, что вы делаете\работаете (программировать, рисовать, играть на скрипке) и, в принципе, вы бы с радостью занимались этим до конца жизни (даже, возможно, после выхода на пенсию), то ответ на вопрос очевиден. Через 5 лет я хочу заниматься тем же самым и вижу себя в той же самой должности с теми же самыми обязанностями, что и сейчас, потому что я люблю то что я сейчас делаю.
2. Моя зарплата сейчас X рублей, но я хочу 2X (3X… nX). Открываю hh, пишу свою настоящую должность, сортирую по зарплате и смотрю, ЧТО должен знать и уметь топ, который получает 2X\3X. Поэтому ответ будет такой: «Я сейчас умею рисовать карандашами, но я вижу что умение рисовать фломастерами оплачивается намного выше. Поэтому за эти 5 лет я хочу научится хорошо рисовать фломастерами, а потом перейти на эту должность.» Это называется карьерный рост.
3. ЗП роли не играет, я устраиваюсь работать эникеем, но хочу быть директором завода: тут тоже, что и пункт 2. Открываем hh, смотрим что должен знать\уметь сотрудник в определённой должности и идём к этому.

То есть вопрос то по сути простой: что вы хотите делать и кем хотите быть через какое то время. Пока никем не хотите? Хотите просто «закрепиться» после института? Так и надо отвечать: я хочу приобрести опыт, поработать в конторе, выполняя свои обязанности посмотрю что мне больше нравиться и буду развиваться (читать+учить+практика) в этом направлении.

Опять же, если вы отвечаете что-то невнятное, то значит глобальной цели у вас нет и поэтому вы будете делать то что вам скажут. А как раз это и требуется, вы приняты ))
UFO just landed and posted this here
Давайте что-нибудь похардкорнее.

22. Надо написать функцию, которая вернет «hello world», но при этом в теле функции нельзя использовать ни цифры, ни буквы, а циклы, массивы, объекты можно, но без цифр.

А где хардкор?
function f()
{
  function hello_world(){}
  return hello_world.name.replace('_', ' ');
}
А можно вообще еще круче (с помощью www.jsfuck.com) =)

Длинный код
function f() 
{
 return [][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+!+[]]]+([][[]]+[])[+[]]+([][[]]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(+(!+[]+!+[]+[+!+[]]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(+![]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(+![]+[![]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]](!+[]+!+[]+!+[]+[+!+[]])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]])()([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]][([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]]((!![]+[])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+!+[]]+(+[![]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+!+[]]]+(!![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(+(!+[]+!+[]+[+!+[]]+[+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(+![]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(+![]+[![]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]](!+[]+!+[]+!+[]+[+!+[]])[+!+[]]+(!![]+[])[!+[]+!+[]+!+[]])()(([]+[])[([![]]+[][[]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]+!+[]]]()[+[]])[+[]]+(!+[]+!+[]+!+[]+!+[]+[!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]+!+[]])+[])+(!![]+[])[!+[]+!+[]+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(+[![]]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+!+[]]]+(+(!+[]+!+[]+!+[]+[!+[]+!+[]]))[(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(+![]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([![]]+[][[]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(+![]+[![]]+([]+[])[([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+([][[]]+[])[+!+[]]+(![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[+!+[]]+([][[]]+[])[+[]]+([][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]])[!+[]+!+[]+[+[]]]](!+[]+!+[]+!+[]+[!+[]+!+[]+!+[]])+(!![]+[][(![]+[])[+[]]+([![]]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+([][[]]+[])[!+[]+!+[]];
}

или так
function hello_world(){
  return arguments.callee.name.replace('_', ' ');
}
7. Вместить три блока 20X20px в ряд, в блок шириной 60px, при этом у блоков должны быть границы

получается некорректный ответ поскольку используется outline, хотя можно использовать для вложенных блоков border + box-sizing: border-box
я думаю, что сейчас и флексы с бордером сработают. Увы, на этот вопрос на собесе я ответила с подсказками, там ждали именно использования outline.
Отличная статья!
Сборник задач 2018.
Хорошо бы корректно формулировать вопросы.

«1. Есть некоторая строка (var str = 'fgfggg';), что будет, если мы возьмем str[0]?» — будет вычислено значение str[0].
«5. Дано дерево, надо найти сумму всех вершин.» — интересно, как можно складывать вершины? Например, в вершинах лежат функции.
«13. Есть несколько слов, определить состоят ли они из одних и тех же букв('кот', 'ток', 'окт')» — тоже кривая формулировка и неправильное решение 'ттт' и 'т' состоят из одних и тех же букв.
«21. Что будет выведено в консоль, как можно модифицировать пример что бы он возвращал правильный результат(назовите как можно больше способов)?» — что такое «правильный результа»? Почему текущий результат неправильныё неизвестно.
«22. Надо написать функцию, которая вернет «hello world», но при этом в теле функции нельзя использовать ни цифры, ни буквы, а циклы, массивы, объекты можно, но без цифр.» — решение полностью состоит из букв.

Ну и т.д.
«35. Сортировка пузырьком.»
Зачем кто-то будет использовать пузырек неизвестно.
Про нее нужно знать только то, что она ненужна :)
Не поверите, но есть ряд случаев, когда пузырёк более оптимален. Несмотря на квадратичную асимптотическую сложность, он имеет очень малый константный множитель, что может дать существенный выигрыш в быстродействии.

Пример 1: массив содержит малое (до 3..5..7) количество элементов. Используется например при медианной фильтрации каких-то входных данных. Если мы окном идём по входному потоку и выполняем медианную фильтрацию, то пузырёк будет эффективнее остальных методов до определённой критической длины, но и после неё он будет медленно уступать в производительности другим методам.
Пример 2: массив почти упорядочен или заведомо известно, что сортировка требует ограниченного количества проходов по массиву. Тут асимптотика вплоть до линейной будет.

Короче, надо будет как-нибудь побенчить и написать статью про преимущества пузырьковой сортировки.
Хорошая статья. Но разве не лучше указать в заголовке область?
скажем «Задачи с собеседований (web front-end)».

А то я уже приготовился читать TOP10-подборку маразматическо-смешных вопросов, которыми оные HR от излишнего рвения любят иногда грузить подателей резюме… а тут банальная js-ина)

— Кстати, про css-центрирование по горизонтали и вертикали разве ни разу не спросили?

А я бы спросил. Особенно после того, как полез я тут выяснять как это делать… и отгреб на 5 разных сайтах 25 разных вариантов, из которых у меня не получилось запустить ни один. Я не очень силен в css, да. А получилось, кстати, запустить код из комментариев.

Вот вы бы как сделали центрирование в ячейке (div) который преобразует внутреннюю модель таблицы в визуальное представление? В свойствах ячейки таблицы (в модели) есть свойства valign и halign со значениями 'start', 'middle' и 'end'. Размеры содержимого ячейки и внешнее обрамление (за границами вашего div) могут быть любые. Надо что бы ваше позиционирование работало всегда.
  1. Вместить три блока 20X20px в ряд, в блок шириной 60px, при этом у блоков должны быть границы.

Краше будет, если юзать


box-sizing: border-box;

Что, в принципе, из коробки идет во многих фреймворках

Объясните, пожалуйста, человеку ещё не очень хорошо разбирающемуся в JS, почему [].slice.call(arguments, 1) работает? Я понимаю, почему нельзя arguments.slice(1) — arguments это не Array, а объект и у него нет метода slice. Но при вызове [].slice.call(arguments, 1) arguments будет this для функции slice, т.е., по смыслу будет идентичен вызову arguments.slice(1) — который невозможен ))
Я не очень понимаю этот механизм.

Представьте, что this — это аргумент функции. Тогда код слайс выглядит как-то так:


Array.prototype.slice = function (this, index ...) {
  // this - это массив
}

В прототипе массива эта функция есть, потому когда мы вызываем [].slice — функция берется из прототипа и аргумент подставляется языком автоматически.
arguments — странный объект и там нету этой функции в прототипе, но мы можем сказать JS-движку: "а подставь ка в эту функцию в качестве this что-то другое".
Именно это мы и делаем:


var sliceFn = Array.prototype.slice
sliceFn.call(arguments, index);
// теперь в качестве аргумента this в функции будет именно то, что нужно
Да, точно, надо воспринимать вызов array.slice(1) как вызов slice(array, 1), а не наоборот. Спасибо.
В [] не будет найден метод slice, затем поиск пойдет в прототипе массива.
call позволяет вызвать метод в другом контексте(фактически воспользоваться «чужим методом»). Аналогична запись Array.prototype.slice.call(arguments, 1).
slice может принимать как один аргумент, так и два. Если мы передаем один, то метод вернет подмассив, который содержит значения исходного, начиная с индекса и до конца исходного массива.
У arguments нет метода slice даже в прототипе, поэтому ошибка.

Сейчас есть Spread и Rest операторы.
function getStr(...arg) {
	return arg.slice(1).join(arg[0]);
}
Задача 22

function getHelloWorld()
{
  var codesStr = '.,,.... .,,. .,,........ .,,........ .,.,. ,...,.. .,.,.........';
  var codes = codesStr.split(' ');

  var word = '';

  for(var k in codes){
    var letters = codes[k].split(',');
    var charCode = '' + letters.shift().length + letters.shift().length + letters.shift().length;
    word += String.fromCharCode(charCode);
  }

  return word;
}


Вернет 'hello w', далее по аналогии…
Что-то у №23 какое-то жуткое решение нахождения суммы)) Вроде бы просто:

const arraySumm = (arr) => arr.reduce((prev, curr) => prev + curr,0);

И затем просто вызывается через
arraySumm(СЮДА_МАССИВ)
Была у меня задача на собеседовании:
Есть кладбище с могилками. На всех могилках, как водится, присутствуют дата рождения и смерти. Надо написать функцию, которая по этим данным определит, в каком году из 20 века жило максимальное количество людей, лежащих на этом кладбище.
Решать надо было на листочке карандашом. Функция на самом деле не сложная, решается одним объектом и перебором массива данных с инкрементом количества живущих в итерируемом году.
Самое смешное — я знал решение этой задачи (во время обучения нечто подобное разбирали), а на собеседовании — начисто забыл.
Решил (вместе с рукописным вводом на бумагу) минут за 10.
Попытался решить 13 в одну строчку:
function sameWords(arr) {
  return arr.map(item => item.split("").sort().join("")).filter((item, i, arr) => item === arr[0]).length === arr.length;
}
Думаю, с find можно короче и логичнее:
function sameWords(arr) {
  return arr
    .map(item => item.split("").sort().join(""))
    .find((item, i, arr) => item !== arr[0]) == null;
}
Цирк с конями продолжается. Вся та же вечная проблема: на собеседованиях спрашивают те реализации, которые в продакшне строго противопоказаны. За половину или даже две трети приведённых выше примеров, будь они в коде, я бы своим младшим коллегам голову бы оторвал.
Ага, особенно каррирование, когда в зависимости от аргументов возвращается или значение, или функция. Вот нежданчик может получиться.
Вопрос номер 40 можно еще решить так:

function getObj (arr) {
    return arr.reduce((obj, item) => {
        obj[item.name] = item.value;
        return obj;
    }, {});
}
Мне так нравится современная мода писать код с квадратичной сложностью для линейного алгоритма. Прям квинтэссенция ФП в JS. Максимум тупости ради понтов.

Думаете, там 1000 полей в объекте будет?

В задаче не сказано, сколько полей там будет и как часто она будет вызываться. Среди трех одинаковых по стоимости поддержки вариантов однозначно следует выбрать один из тех двух, которые имеют линейную сложность, а не квадратичную. И это не преждевременная оптимизация, ибо третий вариант никаких преимуществ кроме выпендрежа не имеет.
В задаче не сказано, сколько полей там будет и как часто она будет вызываться.

Значит, мы можем спокойно предположить, что их будет 10-20.


И это не преждевременная оптимизация, ибо третий вариант никаких преимуществ кроме выпендрежа не имеет.

Как минимум, в нем нет мутабельных операций, то есть он проще, понятнее, удобнее в поддержке. Уже этого достаточно, чтобы предпочесть этот вариант любым другим, данным свойством не обладающим (ну и да, иммутабельно за O(n)) на js это не решается).
Присваивание в reduce, кстати, вообще зашквар, за которое бы руки отрывать.

Значит, мы можем спокойно предположить, что их будет 10-20.

Нет, не может. Мы понятия не имеем, сколько их будет, в условии задачи этой информации нету.

Как минимум, в нем нет мутабельных операций, то есть он проще, понятнее, удобнее в поддержке

Я сегодня кушал хлопья, а значит вы ошибаетесь. Выводы где-то настолько же последовательные. Факт наличия иммутабельности никак не делает какое либо решение проще, понятнее и уж тем более удобнее в поддержке.

Хочу обратить внимание, что иногда иммутабельность и правда делает код значительно проще, понятнее и удобнее в поддержке. Но это не значит, что любой иммутабельный код — такой.

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

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


Факт наличия иммутабельности никак не делает какое либо решение проще, понятнее и уж тем более удобнее в поддержке.

Делает, именно в этом и состоит плюс иммутабельности.


Хочу обратить внимание, что иногда иммутабельность и правда делает код значительно проще, понятнее и удобнее в поддержке.

В данном случае именно так ситуация и обстоит.


Зато зачем-то выполняется тонна ненужной работы

Какой?
И вообще, то, что js линейный код выполняет за квадратичное время — проблема js, а не программиста.

Если в задаче что-то не оговорено, то мы можем делать любые разумные предположения касательно этого момента.
А я вот считаю, что разумное предположение — 100 элементов.

Делает, именно в этом и состоит плюс иммутабельности
Неплохо хоть какую-то аргументацию.

В данном случае именно так ситуация и обстоит.
Нет, не так.

Какой?
К примеру, создание ненужного объекта на каждом шаге цикла. Перенос всех уже существующих элементов в этот объект. Удаление предыдущего объекта.
А я вот считаю, что разумное предположение — 100 элементов.

Как часто вам встречаются объекты со 100 полями?


Неплохо хоть какую-то аргументацию.

А какой по-вашему плюс иммутабельности?


Нет, не так.

Ну как же не так? Вы получаете код с прямым потоком исполнения вместо непонять чего что в середине что-то непонятным образом как-то меняет.


К примеру, создание ненужного объекта на каждом шаге цикла. Перенос всех уже существующих элементов в этот объект. Удаление предыдущего объекта.

Прикольно, что два пункта из трех на линейность решения никак не влияют. И, кстати, самое забавное, что в подавляющем большинстве кейсов именно из-за выделения памяти решение окажется медленнее, а не из-за того, что оно квадратичное…
Но, опять же, это все проблемы тормозного js, что он не может быстро память выделять (и в принципе не в состоянии оптимизировать данный код до мутабельной реализации внутри), а не программиста.

Как часто вам встречаются объекты со 100 полями?
Каждый рабочий день. А вам?

А какой по-вашему плюс иммутабельности?
А вы таки из этих?

Ну как же не так? Вы получаете код с прямым потоком исполнения вместо непонять чего что в середине что-то непонятным образом как-то меняет.
Все очень понятно.

И, кстати, самое забавное, что в подавляющем большинстве кейсов именно из-за выделения памяти решение окажется медленнее, а не из-за того, что оно квадратичное

Ага. Я догадываюсь об этом (увы, не могу с уверенностью сказать, ибо не проверял).
Как часто вам встречаются объекты со 100 полями?
Хочу обратить внимание, что в данном случае нас не интересует как часто мы встречаем объект на 100 полей. Данная функция ускоряет доступ к объектам массива по ключу. То есть у нас, к примеру, есть тысяча юзеров и мы вместо того, чтобы искать каждый раз их по всему массиву хотим занести в хеш и искать по имени. Если у нас массив до 10-ти элеметов, то эта оптимизация не имеет особого смысла. А вот если юзеров тысяча, то неплохо занести их в кеш. Как результат этот кеш станет объектом с тысячей полей, где ключ — имя пользователя, а значение — ссылка на его объект.
А вот если юзеров тысяча, то неплохо занести их в кеш

И потому я хочу обратить внимание на альтернативы, которые мы имеем при тысяче пользователей:

* 1 созданный объект
* 1 000 присваиваний

против

* 1 000 созданных и уничтоженных объектов
* 500 000 присваиваний
Хочу обратить внимание, что в данном случае нас не интересует как часто мы встречаем объект на 100 полей. Данная функция ускоряет доступ к объектам массива по ключу.

В постановке задачи сказано "объект", а не "хеш-таблица".


Каждый рабочий день. А вам?

Сейчас проскролил файлик с апи (12к строк), насчитал 6 сущностей с 30+ полями (мог парочку пропустить, пусть их будет 10).


А вы таки из этих?

И все же, по-вашему, какой плюс от иммутабельности? То есть, если иммутабельный код не становится проще, понятнее, удобнее в поддержке, то в чем смысл? Ведь практически всегда иммутабельная реализация требует дополнительных усилий. Еще и издержки по производительности вдобавок.


Все очень понятно.

Ну вам понятно, мне — не очень. Мне более понятны функции, в которых нет сайд-эффектов, по крайней мере внешних. Внешний сайд-эффект в анонимной функции — это вообще code smell сам по себе, и допустимо только при наличии явной причины.


И потому я хочу обратить внимание на альтернативы, которые мы имеем при тысяче пользователей:

А я не хочу, потому что в таком контексте эта функция применяться не будет, а будет на объектах с 20 полями.


Так рассуждая — может, ваш хеш вообще в память не влезет? Давайте предусмотрим соответствующие механизмы для сброса на жесткий диск, чтения, синхронизации?


Т.е., нам надо, чтобы сущность вела себя как js объект, но при этом объект в память не влазит.

И все же, по-вашему, какой плюс от иммутабельности? То есть, если иммутабельный код не становится проще, понятнее, удобнее в поддержке, то в чем смысл?

Смысл — в упрощении отслеживания потоков данных: хорошо видно кто мог менять структуру, а кто — нет. Еще иногда на иммутабельность завязывают архитектурные фишки, вроде того как сделали в redux.


Все эти причины "работают" только на больших масштабах кода, как минимум код должен перестать помещаться в экран.

Смысл — в упрощении отслеживания потоков данных: хорошо видно кто мог менять структуру, а кто — нет.

А это не ведет к тому, что код становится проще, понятнее, удобнее в поддержке?


Еще иногда на иммутабельность завязывают архитектурные фишки, вроде того как сделали в redux.

В Redux мутабельная архитектура.


Все эти причины "работают" только на больших масштабах кода, как минимум код должен перестать помещаться в экран.

Вы можете привести хоть один пример использования в мейнстриме иммутабельности именно в архитектуре, а не в тех самых однострочниках? Потому что в том же Redux именно так — за пределами двух строчек все полностью мутабельно.
Просто практика с вами не согласна, выходит.

А это не ведет к тому, что код становится проще, понятнее, удобнее в поддержке?

Ведёт, но только для больших объёмов кода. Потому что в пятистрочной функции всё это и без иммутабельности видно.


В Redux мутабельная архитектура.
Вы можете привести хоть один пример использования в мейнстриме иммутабельности именно в архитектуре

Там есть один важный для архитектуры инвариант, из которого следует иммутабельность хранимых в сторе данных:


Равенство двух версий одного объекта в сторе по ссылке эквивалентно отсутствию изменений между ними.


Этот инвариант позволяет, в том числе, использовать PureComponent с его неглубоким сравнением свойств так, как будто сравнение глубокое.

Там есть один важный для архитектуры инвариант, из которого следует иммутабельность хранимых в сторе данных:

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


Ну можно вот на рассматриваемом примере. Иммутабельное решение:


function getObj (arr) {
    return arr.reduce((obj, item) => ({ ...obj, [item.name]: item.value }), {});
}

мутабельное решение:


function getObj(arr) {
    var obj = {};

    arr.forEach(function(item){
        obj[item.name] = item.value;
    });

    return obj;
}

другое мутабельное решение (ака редакс):


function getObj(arr) {
    var obj = {};

    arr.forEach(function(item){
        obj = { ...obj, [item.name]: item.value };
    });

    return obj;
}

Общая логика кода остается как в мутабельном варианте.

Так этот инвариант ничего не дает с точки зрения более понятного кода

А я что, говорил что-то про понятность redux?


другое мутабельное решение (ака редакс):

Вот не надо. Нигде в гайдах по редаксу нет рекомендаций писать вот так. Вы взяли всю архитектуру целиком, выкинули из нее все что показалось лишним, остаток записали в одну функцию — и получили бредовый код. Не надо так делать.


Кстати, точно такую же хренотень вы получите если возьмете первый пример, и раскроете в нем метод reduce...

Вот не надо. Нигде в гайдах по редаксу нет рекомендаций писать вот так.

При чем тут гайды? Это то как работает сам редакс, с целом. Архитектурно.


Вы взяли всю архитектуру целиком, выкинули из нее все что показалось лишним

Нет, я как раз архитектуру оставил. Именно так работает редакс — у вас есть state, и вы его апдейтите при помощи конструкции вида state = { ...state, f(state) };


Кстати, точно такую же хренотень вы получите если возьмете первый пример, и раскроете в нем метод reduce...

Нет, не получу. Можете сами раскрыть и проверить, reduce не меняет никаких внешних переменных.

В постановке задачи сказано «объект», а не «хеш-таблица».
В JS первое реализуется через второе.

Сейчас проскролил файлик с апи (12к строк), насчитал 6 сущностей с 30+ полями (мог парочку пропустить, пусть их будет 10).
Я уверен, что вы сможете вспомнить объекты, в которых более 100 полей если попытаетесь.

То есть, если иммутабельный код не становится проще, понятнее, удобнее в поддержке, то в чем смысл?
Иногда — становится. Но не любой код такой.

Мне более понятны функции, в которых нет сайд-эффектов, по крайней мере внешних. Внешний сайд-эффект в анонимной функции — это вообще code smell сам по себе, и допустимо только при наличии явной причины.
Где вы видите тут внешние сайд-эффекты? Эта функция чистая (pure) и именно это реально важно для поддержки кода, а не то, что внутри она использует модные практики для понт-программирования. Она имеет все преимущества, которые дает чистота. У неё предсказуемый результат от аргументов и она не имеет сайт-эффектов. Она не меняет структуру (как метод splice массива), а создает новую (как метод slice)

function getObj(arr) {
    var obj = {};

    arr.forEach(function(item){
        obj[item.name] = item.value;
    });

    return obj;
}


Я, правда, не столь категоричен как вы и не осуждаю побочные эффекты (я не считаю, что наличие побочных эффектов портит код, это просто другой путь), но тут их всё-равно нет, так что смысла обсуждать это — тоже нету.

А я не хочу, потому что в таком контексте эта функция применяться не будет, а будет на объектах с 20 полями.
Почему не будет? Это самое логичное применение. Зачем ещё может существовать такая функция? Если мы будем делать маппин максимум 20 объектов, то тут и проход по массиву для поиска подойдёт.
В JS первое реализуется через второе.

Это детали реализации. Можно дальше пойти и сказать, что и то и то — байты в памяти. Но важно не это, важно, как мы эти байты интерпретируем и как используем. Если вы сказали, что что-то объект — оно используется как объект, а если что-то — хеш-таблица, то оно используется как таблица.
Здесь ситуация как, например, с паттернами билдер и фабрика. С точки зрения реализации — это один и тот же паттерн. Но они по-разному применяются, и по-этому мы называем их по-разному.
Так что никакой причины отождествлять хеш-таблицы с объектами (несмотря на то, что где-то там они реализованы при помощи одних и тех же механизмов) — нет.


Я уверен, что вы сможете вспомнить объекты, в которых более 100 полей если попытаетесь.

Ну может и вспомню одну-две штуки. Ну и что?


Иногда — становится.

Когда, например? Хотелось бы просто четко понять отличия такого кода, когда "становится", от обсуждаемого.


Где вы видите тут внешние сайд-эффекты?

Внешние сайд-эффекты в лямбде. Вот в этой:


function(item){
        obj[item.name] = item.value;
});

Почему не будет?

А почему будет? Раз нет причин считать, что будет — считаем, что не будет. Это разумно.


Зачем ещё может существовать такая функция?

Ну, например, такой у нас протокол общения с сервером. Вместо нормального жсона приходит такая вот хрень, в которой объекты выдаются списком [[k1, v1], [k2, v2]...] а не в обычном представлении ({}).


Если мы будем делать маппин максимум 20 объектов, то тут и проход по массиву для поиска подойдёт.

Ну это же просто неудобно — каждый раз, когда вам понадобится поле любого пришедшего с сервера объекта, искать проходом по массиву. Проще преобразовать объект и потом спокойно обращаться к полям как object.field, еще и с наличием типизации.

Здесь ситуация как, например, с паттернами билдер и фабрика. С точки зрения реализации — это один и тот же паттерн
Эмс. Вы уверены, что не упустили парочку деталей?

Внешние сайд-эффекты в лямбде.
Ааа. Ну тогда давайте так. Я тоже не вижу смысла в той лямбде. Чем проще код — тем лучше.

function getObj(arr) {
    const obj = {};

    for (const item of arr) {
        obj[item.name] = item.value;
    }

    return obj;
}


Ну это же просто неудобно — каждый раз, когда вам понадобится поле любого пришедшего с сервера объекта, искать проходом по массиву.
Эй, мы ведь крутые функциональщики, ничего неудобного!
arr.find(byName('targetName'))
// покруче будет, чем
castToObjectByName(arr)['targetName']


Ну может и вспомню одну-две штуки. Ну и что?
Не знаю, это ведь вы у меня объект такой просили.

Когда, например? Хотелось бы просто четко понять отличия такого кода, когда «становится», от обсуждаемого.
Э нет, давайте не съезжать. Вы утверждаете, что в данном случае иммутабельность чем-то помогает поддержке — вы и доказывайте. Я лишь согласился, что иногда она может быть полезной и не собираюсь начинать перечислять все случаи.

Вместо нормального жсона приходит такая вот хрень, в которой объекты выдаются списком
Этому, пожалуй, должна быть причина.
Эмс. Вы уверены, что не упустили парочку деталей?

Абсолютно.


Ааа. Ну тогда давайте так. Я тоже не вижу смысла в той лямбде. Чем проще код — тем лучше.

Так уже лучше. Но что если в процессе надо значения как-то обрабатывать? Фильтровать?


Эй, мы ведь крутые функциональщики, ничего неудобного!

В смысле ничего неудобного? С чего бы это писать arr.find(byName('targetName')) менее неудобно, чем просто object.targetName?


Э нет, давайте не съезжать. Вы утверждаете, что в данном случае иммутабельность чем-то помогает поддержке — вы и доказывайте.

Так я и доказываю, от противного. То есть, предположим, что ваше утверждение истинно — и в данном примере от иммутабельности толку нет. С другой стороны имеем некоторое утверждение, что в каких-то случаях от иммутабельности толк есть. Я хочу показать, что эти два утверждения друг другу противоречат. Для этого мне требуется знать, а в чем, по-вашему, толк от иммутабельности в тех случаях, когда вы видите этот толк.


и не собираюсь начинать перечислять все случаи.

Зачем же все? Достаточно пары показательных примеров. Просто чтобы продемонстрировать свою мысль.


Этому, пожалуй, должна быть причина.

Да как обычно — исторически сложилось. Тому, что вы 1к юзеров храните списком вместо хеша, тоже ведь причина какая-то есть.

Так уже лучше. Но что если в процессе надо значения как-то обрабатывать? Фильтровать?

Слишком много обязанностей для функции, которая делает из массива объект. Передавайте отфильтрованный массив.

Не расстраивайте меня такими идеями, я про вас хорошего мнения.

чем просто object.targetName?
Нет у вас никакого object. Есть только array, а у него — нету никакого targetName.

в данном примере от иммутабельности толку нет. С другой стороны имеем некоторое утверждение, что в каких-то случаях от иммутабельности толк есть. Я хочу показать, что эти два утверждения друг другу противоречат
У вас тут пробел в логике. Эти утверждения друг другу не могут противоречить. Вот смотрите. Вы говорите:
— Все машины синие, потому и эта тоже — синяя
На что я отвечаю:
— Согласен, синие машины бывают, но эта — не синяя.

И вы стараетесь найти противоречие в моем утверждении. Но там противоречия нету. То, что бывают синие машины ещё не означает, что все машины синие.
(В данном случае «синяя машина» ~ «полезная иммутабельность»).

Да как обычно — исторически сложилось. Тому, что вы 1к юзеров храните списком вместо хеша, тоже ведь причина какая-то есть.

Я храню тысячи юзеров списком потому что это лучший способ хранения тысячи юзеров. Хеш специфичен для предметной области. Где-то ключём может быть айдишник, а где-то имя, где-то ключём может быть какой-то флаг, а значением — массив всех юзеров, которые имеют такое значение флага. Так что — мне теперь хранить все варианты хешей? Потому юзеры хранятся в самой логичной и подходящей форме — в массиве.

Слишком много обязанностей для функции, которая делает из массива объект.

Мы тут предполагаем, что нам в принципе нужна ф-я, которая делает из массива объект. Что, если это просто часть преобразования, которая не несет смысла сама по себе?


Я к тому веду, что у нас может быть что-то вроде arr.filter.map.reduce — в таком виде этохорошо читается и легко исправляется, т.к. каждое преобразование четко выделено (и достаточно очевидно что в большей части случаев выделять каждый map или filter в отдельную ф-ю смысла какого-либо нет). В случае мутабельного решения все будет намешано в цикле.


Нет у вас никакого object. Есть только array, а у него — нету никакого targetName.

Так я использовал обсуждаемую ф-ю, и получил object. Теперь могу по селектору получать доступ. Вместо того, чтобы писать find каждый раз.


У вас тут пробел в логике. Эти утверждения друг другу не могут противоречить.

Конечно пробел, чтобы его устранить — мне надо знать ответ на заданный вопрос. То есть в вашем случае, если вы ответите, то получится, что указанная машина — как раз синяя.


Так что — мне теперь хранить все варианты хешей?

Очевидно, хранить тот, который вам нужен. У вас ведь ф-я строит вполне конкретный хеш. Его и храните.

Что, если это просто часть преобразования, которая не несет смысла сама по себе?
Я за декомпозицию.

В случае мутабельного решения все будет намешано в цикле.
Не понимаю ваше «намешано».

Так я использовал обсуждаемую ф-ю, и получил object. Теперь могу по селектору получать доступ. Вместо того, чтобы писать find каждый раз.
Не обязательно писать каждый раз. Можно просто создать локальную функцию:
const get = name => arr.find(byName(name));


Хотя вы зараз можете придраться к нечистоте, потому давайте сразу сделаем стильненько:
const getFrom = arr => name => arr.find(byName(name));

const get = getFrom(arr);


Конечно пробел, чтобы его устранить — мне надо знать ответ на заданный вопрос
Нет, не нужно. Мой ответ никак не даст вам возможности обосновать свои слова. Потому что даже если я скажу полную глупость — это никак не может являться аргументом.

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

И комментарии не только я читаю.

Так что давайте вы перестанете аппелировать к моей личности и поищите какие-нибудь объективные аргументы для своего утверждения.

Очевидно, хранить тот, который вам нужен. У вас ведь ф-я строит вполне конкретный хеш. Его и храните.

А зачем хеш хранить? Давайте сразу отрендеренную страницу, а юзеров хранить не будем.

Вы мне предлагаете хранить промежуточное представление, которых может быть любое количество. Уверен, вы сами считаете это глупым, и не совсем понимаю, зачем вы это вообще предлагаете.

Я за декомпозицию.

А я за понятный, поддерживаемый код. Довольно-таки очевидно, что есть определенный предел декомпозиции, за которым указанная декомпозиция начинает вредить (можно рассмотреть предел декомпозиции, где каждая ф-я состоит из максимум двух операций — очевидно, это будет адъ, а не код). Я этот предел провожу там, где ф-и начинают терять осмысленность. Если можно вынести ф-ю и при этом она будет осмысленной — можно выносить. Если нельзя — не надо выносить.


Не понимаю ваше «намешано».

Логика всех операций перемешана друг с другом и с самой логикой итерирования. "перемешана" = "не отделена", если угодно.


Не обязательно писать каждый раз. Можно просто создать локальную функцию:

То есть вы предлагаете везде для каждого требуемого поля определять по локальной ф-и + по ф-и вида byName? И говорите, что это "удобно"?
Окей, у нас, очевидно, разные представления об удобстве. По-этому и оценка удобства обсуждаемой ф-и не совпадает.


С-но, именно за тем я и спрашивал про "удобную иммутабельность" — понять, что вы подразумеваете под удобством, потому что, очевидно, нет смысла обсуждать является ли что-то удобным, не определив, для начала, некое общее понимание этого термина. Ну вот определили, теперь ясно все, я предпочитаю делать "get = object.field" вместо "const get = name => arr.find(byName(name))" + "const get = getFrom(arr);" и иммутабельные решения вместо мутабельных. Вы — наоборот.

Не поняла наезда на ребят с задачей про Object.create(), там же написано что проперти можно задать вторым параметром прямо

Sign up to leave a comment.

Articles