Vikhrmodels/habr_qa_sbs huggingface dataset:
Вопрос: Событие нового дня?

Лучший ответ:
setTimeout дает гарантию, что коллбек выполнится не раньше, чем через указанное число милисекунд. 
Коллбеки истекших таймаутов вызываются в начале цикла событий. Т.е. не могут быть вызваны прежде чем текущй цикл закончится.
Особо хитрые браузеры вообще умеют замораживать таймауты в неактивных вкладках.
Т.е. ну ты понел, на setTimeout надейся, а секунды все равно проверяй.

Худший ответ:
Повлияют. Как и любые зависания. 
Не знаю вашей задачи, но думаю лучше будет запускать задачу каждую минуту (или сикунду, зависит от той точности что вам нужна) и сравнивать день на прошлой и на текущей итерации
Вопрос: Как отправить команду по COM/Serial port с помощю nodejs?

Лучший ответ:
'H' на конце - это всего лишь признак шестнадцатеричного значения, передавать его в Buffer.from не надо.
Значение BCC необходимо предварительно рассчитать, взяв XOR всех байтов, входящих в команду. XX - просто обозначает расчётное значение (в данном примере должно быть 23H).
Соответственно, строка должна выглядеть так:var data = Buffer.from("045002760323", "hex");
Ну и, если полностью прочитаете описание протокола, то увидите, что после отправки команды необходимо получить от диспенсера подтверждение (ACK), ответ, и выдать ACK подтверждая получение ответа.

Худший ответ:
Играть с оборудованием на языках с динамической типизацией строго не рекомендуется. Напишите демон на с/с++ и обращайтесь к нему.
Вопрос: Почему у rabbitmq такая низкая производительность?

Лучший ответ:
В гугле по словам "rabbitmq" и "rpc" выдаётся ссылка на оф.документацию по Direct reply-to, Вы пробовали такой механизм? Создание/удаление очереди ради получения одного ответа это очень накладно. 50/400rpc это вообще не о чём, даже для RabbitMQ (конечно всё зависит от выделенных ресурсов, хранению на диске и т.д.).

Худший ответ:
Можно попробовать кластеризацию для RabbitMQ и поиграться с настройками. 
Еще есть вариант заюзать Apache Kafka - более мощное и высокопроизводительное решение.
Вопрос: Как разделить разработку backend и frontend?

Лучший ответ:
Теоретически конечно могут возникать ситуации, когда и бек, и фронт, лезут редактировать одно и то же место, в одном и том же файле, плюс-минус в одно и то же время. Что может приводить к merge conflicts. 
Но, во-первых, такое должно происходить крайне редко. Во-вторых, если это происходит, то это вопрос не совсем корректных процессов или архитектуры. В третьих, такие конфликты легко резолвятся тимлидом.
Поэтому, лично я не вижу никакой проблемы в том, что работа идет в feature branches, каждый делает свою часть, а потом это все мерджится.

Худший ответ:
Сразу скажу, что не имею огромного опыта, но скажу как делаем мы.
У нас совсем маленькая команда. В основном пишем веб-приложения(CRM и тд) на Laravel+Vue/AngularJS. Делаем один репозиторий на BitBucket, раздаем права и как бы все. Backend-еры не лезут в код фронта и наоборот. Следовательно никаких конфликтов не возникает в гите. Ну а если возникает, то там гит сам подсказывает, что да как делать. В основном это просто git add * git commit -m "message". И все конфликты уходят.
Никаких неудобств не испытываем с битбакетом. Опять же можно привязать ключи и не вводить постоянно пароль. И все шутро работает.
Вопрос: Какой JavaScript фреймворк выбрать?

Лучший ответ:
Посвятите 1-2 дня для того, чтобы познакомится с основным синтаксисом и идеологией этих фреймворков и выберете тот, что вам лично ближе. Самый верняковый путь, чем слушать мнение рандомных людей.
Если вам интересны перспективы, то в аутсорсовых фирмах — подавляющее большинство Angular проектов, в продуктовых по миру чаще встречается React, а комьюнити сейчас больше всего хвалит и хайпит Vue.

Худший ответ:
либо Angular 4, либо Vue
Сильно спорное утверждение.
Если действовать методом исключения из "большой тройки", скорее, первый кандидат на вылет именно Angular
Вопрос: Стекирование коммутаторов: действия при выходе из строя одного элемента?

Лучший ответ:
1. меняется, если есть запасной. если запасного нет - не меняется.
2. переключаются, если есть куда. если нет куда - не переключаются.
вообще эти два пункта должны оговариваться в инструкции по обслуживанию отказов или в чём-то подобном. настройка других коммутаторов должна предполагать такой манёвр.
3. докладная, если есть начальство. если нет начальства - ну вы поняли...
вообще этот пункт должен оговариваться в должностной инструкции или в чём-то подобном. если начальство ждёт от вас докладных - оно как правило предварительно об этом сообщает.

Худший ответ:
Если настроены по разному не заменить, не перетыкнуть
Вопрос: Не могу разобраться в ошибках Gulp?

Лучший ответ:
Это не ошибки, а предупреждения по поводу обновления зависимостей в самом gulp. Не обращайте на них внимание. 
Gulp нужно установить еще локально в проекте. И сам gulp не может "бросать" на локалхост, потому что это таск раннер. Это делает плагин browser-sync, а в конфиге к нему можно прописать нужный порт.
Изучите получше документацию по gulp, чтобы понимать как его использовать

Худший ответ:
+1 к ответу nakree 
И вот посмотрите Скринкаст по Gulp
Вопрос: В какой программе/редакторе рисуют такие картинки?

Лучший ответ:
Судя по отражениям, фокусу и теням, скорее всего это редакторы 3D, например блендер, 3д макс и подобные.

Худший ответ:
Скорей всего иллюстратор или 3Dmax
Вопрос: Телеграм бот, как спрятать ссылку на фото в посте?

Лучший ответ:
bot.send_message(message.chat.id, 'Котик' +'[.]' + '(' + photo + ')', parse_mode='markdown')
bot.send_message(message.chat.id, f'Котик[.]({photo})', parse_mode='markdown') # python 3.6+

Худший ответ:
Для отправки фото без текста есть специальный метод.sendPhoto
Если нужен текст + фото, то это можно сделать только через несколько сообщений. Одним методом для фото можно только указать заголовок.
Вопрос: Какие математические операции выполняет этот код?

Лучший ответ:
это логические и битовые операции.
| - логическое сложение
& - логическое умножение
<< и >>  - сдвиг влево или вправо на количество бит, аналогично умножению или делению на 2 в указанной степени
конкретно как работает &
y = x & 65535
для x=12345
переводим в двоичный вид
11000000111001
переводим 65535 туда же
1111111111111111
выполняем логическое побитовое сложение (правила сам поищи)
результат = 10011000000111000
переводим обратно в десятичный вид
77880
както так)

Худший ответ:
какие конкретно операции он выполняетпобитовые
Вопрос: Прошивка для RaspberryPi которая превращает ее в контроллер GPIO?

Лучший ответ:
Там и классический Linux позволяет управлять GPIO. Или вы что то ищите особенное?
На самом низком уровне примерно так. Но есть нормальные интерфейсы более высокого уровня

Худший ответ:
WiringPi не подойдет?
Вопрос: Как избежать одновременного UPDATE таблицы базы данных MySQL?

Лучший ответ:
Транзакции всем хороши, но под нагрузкой приводят к замедлению работы приложения и иногда, если не правильно работать с запросами к deadlock-м. 
Можно создать отдельную таблицу в которую записывать запросы пользователей на получение ресурса, например так:
идентификатор пользователя,  идентификатор ресурса,  статус заявки (в очереди, обработана, отклонена), дата и время заявки с точностью до миллисекунд  (ну или числовое поле с автонумерацией).
При нажатии на "купить товар" операция выполняется в два шага, первый шаг - помещаем заявку пользователя в эту таблицу. (несколько пользователей могут придти за одним ресурсом и приоритет будет у того кто пришел первым)
Таблица нужна, чтобы не накладывать блокировок на таблицы БД (блокировки могут быть из-за открытой транзакции) 
Далее второй шаг - запускаем процедуру получения статуса заявки (она должна вернуть ответ получил пользователь свой ресурс или нет,  т.е. обработана его заявка успешно или отклонена).
Обработка заявок - это отдельный серверный процесс, он берет заявки по очереди поступления и обрабатывает (изменяет состояние ресурса в БД и состояние заявки) до тех пор пока у выбранного ресурса хватает количества, все пользователи которым не хватило ресурса получают сообщение о невозможности получить ресурс.

Худший ответ:
Почитайте о  транзакциях, они блокируют поля, пока выполняется UPDATE.
Вопрос: Бесплатная IDE для C++?

Лучший ответ:
Мухи отдельно - котлеты отдельно.
В компилятор НИКТО не встраивает редактор кода, компоненты и формы.
Да и вообще - большинство компиляторов - бесплатные.
А вот среды разработки - которые как раз и содержат все от 4 до 6 пункта - могут быть платные, да.
По факту:
вам нужен Qt. Это фремворк. Прожевывается многими компиляторами. И легко дружит с QtCreator в плане создания форм.

Худший ответ:
Visual Studio 2015-2017 Community edition.
Если нужны новые фичи +ов то можно добавить llvm.
>
С возможностью создавать простые графические элементы (к примеру формы как в Delphi)
RAD в плюсах постепенно уходит на покой, лучше учите WPF и C# для создания GUI. Либо используйте Qt и QtCreator если этот пункт не оч. важен то однозначно VS Community иначе либо C#+Wpf либо QtCreator который в принципе хорош для маленьких проектов(<100MB sources).
Вопрос: Что это за движок?

Лучший ответ:
Судя по всему самописка от товарищей radolaukar_ee

Худший ответ:
wp там у них
Вопрос: Как в Microsoft Office 2016 отключить запросы к интернет ресурсам?

Лучший ответ:
Привет, скопипастил отсюда: https://answers.microsoft.com/ru-ru/msoffice/forum...
чтобы не искать то вот:
ФАЙЛ / Параметры / Центр управления безопасностью / Параметры центра управления безопасностью / Параметры конфиденциальности Снять галочку "Разрешить Office подключиться к Интернету"
+
Подозреваю человек столкнулся с тем что прокся ругается. В общем вышеприведенное + в панель управления==свойства интернета==подключения==настройка сети==Настройка параметров локальной сети==дополнительно== В графе "не использовать прокси-сервер для адресов..." добавить *.microsoft.com
После этого офис 2013 и офис 2016 заткнулись и прекратили спамить окнами авторизации.
Конкретно у меня была проблема на вин10 + 2016

Худший ответ:
Прописал сразу *.microsoft.com;*office.net;*live.com;*office365.com;*office.com;*outlook.com;*office365.fun
Вроде помогло.
Вопрос: Нужны ли теги в современном сайте?

Лучший ответ:
А как иначе юзерам подписываться или блокировать определенные сорта материала?
Другой вопрос - делать ли их обязательными (думаю, не нужно), и не пытаться ли их (ну, скорее - только самую общую часть) извлекать автоматически

Худший ответ:
для сео надо
Вопрос: Какую базу лучше использовать для хранения событий?

Лучший ответ:
MySQL с нормальной структурой и индексами.но получил жестокие задержки при попытке собрать статистику о действиях одного игрока
Ваша структура должна учитывать такую возможность.
Или - учитывать, что часть ответов дается БД быстро (те что нужны сиюминутно же, быстро), а часть (второстепенные, не нужные часто) - медленно.
Если прям хотите очень быстро - см. Tarantool.
Он относится к классу СУБД, дающих ответ максимально быстро.
Если уж на нем у вас будет тормозить - пересматривайте свою архитектуру.

Худший ответ:
postgres с нормальной структурой и индексами
Вопрос: Где находится папка .ssh?

Лучший ответ:
в файле /etc/passwd указаны домашние папки всех пользователей
если же команду выполнять от имени git то можно сделать так:
mkdir ~/.ssh/
nano ~/.ssh/config

Худший ответ:
В шеле ~ раскрывается как домашняя папка текущего пользователя, ~user - как домашняя папка пользователя user: ~/.ssh - для текущего пользователя, ~user/.ssh - для пользователя user.
Выше писали, что можно получить информацию из /etc/passwd, но это неправильный подход: /etc/passwd используется для локальных пользователей. Если в системе настроены другие источники пользователей, например LDAP, в /etc/passwd их не будет. Правильно будет использовать утилиту getent, которая всё это учитывает: 
getent passwd  | cut -d: -f6
Вопрос: Как добавлять данные постепенно в БД?

Лучший ответ:
Аккумулировать данные в сессии

Худший ответ:
Как вам уже заметили в комментариях, вам необходимо погуглить назначения методов HTTP, ибо метод GET вы используете некорректно.
Про сессию уже написали. Ещё вариант - это использовать local strorage на стороне клиента и писать-читать из него (немного поработать с js). 
Если варианты выше не подходят, то можно в отдельной таблице хранить проекты заявок. Т.е. пользователь сначала создаёт проект заявки первым запросом - сохраняем его в отдельную таблицу, а потом на каждом шаге в эту запись добавляются данные с отдельных форм. В финале этот проект становится заявкой - удаляется из таблицы проектов и переносится в таблицу заявок. Это решение не зависит от состояния сессии и local storage. Пользователь может продолжить заполнять заявку с другого клиента в другой сессии, ведь мы храним его проект у себя в базе. Как бонус, таким макаром можно при необходимости организовать пользовательские шаблоны заявок (если форма большая и пользователем большая её часть вводится одинаковая), чтобы быстро создавать новые заявки из сохранённых шаблонов.
Если требованиями not null полей можно немного принебречь, то можно ввести статусы заявки или флаг является ли заявка проектом и хранить их в одной таблице. Тоже, что и в предыдущем варианте, но только всё в одной таблице и в итоге мы просто меняем статус или флаг записи.
Ещё вариант, если у вас есть html, который не меняется по ходу изменения форм (т.е. вы просто меняете куски страниц при переходе по формам), то можно завести скрытые поля, куда дублировать заполнение формы пользователем. В итоге у вас эти скрытые поля заполнены и именно их содержимое отправляется на сервер в итоге. Видел такое на старых проектах.
В проектах с SPA такой проблемы нет, т.к. в таком случае на клиенте просто выполняется управление состоянием и роутингом
Вопрос: Как мягко отказаться от выполнения тестового задания если выслал уже тонну примеров своего кода?

Лучший ответ:
Сказать "я не готов к выполнению тестового задания потому что нет времени."

Худший ответ:
Выполнять тестовое задание:) Так как Вы ищите работу. Предполагаю, с таким подходом Вас не возьмут, так как Вы отвалитесь на этапе "НЕ выполнил тестовое задание".
Вопрос: Почему align-items: center; работает именно так?

Лучший ответ:
Потому что центрируется содержимое section, а не содержимое содержимого section. Хотите чтобы текст в h1 был по центру - добавьте text-align: center;.

Худший ответ:
Спасибо за объяснения.
Вопрос: Почему после обновления пропал Firebug?

Лучший ответ:
Firebug больше не будут развивать. https://addons.mozilla.org/ru/firefox/addon/firebug/

Худший ответ:
Да, была недавно новость, что Firebug уже всё.
Переучивайтесь на встроенные Developer Tools.
Вопрос: Как в html5 реализовать бесшовное воспроизведение аудио петли?

Лучший ответ:
Луп должен повторяться в записанном файле минимум 4 раза.
Когда отыграны первые 3 - делаем перемещение позиции на начало 2-го лупа. (1,2,3,2 и т.д. по кругу)
Тайминг-засечки начала каждого лупа лучше передавать вместе с луп-файлом.
Задача проста: не давать останавливаться плееру через seeking-перемотку.
Никаких "стоп"! Только: 
1. загрузка трэка, 
2. seeking в конец (чтобы предотвратить отложенную буферизацию), 
3. готовность к воспроизведению, 
4. seeking на начало, 
5. пауза. (всё, трэк готов к воспроизведению)
PS: Если кто что еще знает - с удовольствием послушаю!
Спасибо!

Худший ответ:
howlerjs (смело берите вторую версию, успешно опробована в продакшне).
Далее загуглите, как smooth loop делать - уверен, справитесь.
Вопрос: В каких случаях использование фреймворка(например express.js) для nodejs не оправдано?

Лучший ответ:
Неоправдано в следующих случаях:Вы только начали изучать Node.JS и практически ноль в нем. В данном случае лучше сразу разобраться с основами и только затем браться за изучение фреймворков.Когда нужно сделать что-то очень простое и очень быстрое. Например у вас 2-3 функции, которые просто работают с базой. Например счетчик визитов на сайте.Когда фреймворк не вписывается в архитектуру вашего приложения. Например у вас повсюду веб-сокеты и к ним сбоку пытаются прилепить еще и фреймворк.Когда приложение написано для стриминга данных, например мультиплексор какой-нибудь. Тут обычные фреймворки курят в сторонке.

Худший ответ:
Смотря для чего вам этот сервер. Статику отдавать и обычный http-server может.
Да и статику можно руками написать. Для REST API тот же restify на 100% отрабатывает.
Вопрос: Изучение фронтэнда/JS?

Лучший ответ:
и просьба не писать негативные комментарии, поскольку итак в упадке духа и гружусь на эту тему.
Но все же, советую определиться с целью обучения программированию. Если чисто ради денег, а не ради интереса, то вероятнее всего, вы будете очередным "вайтишником". Если у вас уже есть работа, можно не спеша все осваивать без всяких менторов и курсов. Например прочитайте Чарльза Петцольда Код. Тайный язык информатики, это книга поможет понять, что вообще такое код. 
Курсы почти всегда бесполезны, они дадут вам ложное чувство понимания программирования. Самое важное в этой профессии, уметь учиться самому, иначе дальше не потяните. А время изучения основ, самый лучший момент также прокачивать навыки самообучения. Помните, не будет курсов для мидлов-сеньеров, и когда вы пройдете курсы для новичков, дальше вам все также будет непонятно, куда двигаться и как учить. Поэтому советую на легком этапе, пробовать сделать все самой. 
Через пол-года/год активного обучения, попробуйте устроится на работу в команду, это ускорит дальнейший процесс обучения.

Худший ответ:
HTML Академию рекомендую, курсы хорошие на сайте, покупал подписку, на интенсивы не записывался, а находил в записи на небезызвестных ресурсах, они весьма годны. Для начала более чем достаточно. Было бы неплохо вам найти человека, который уже в этой профессии и помогал бы вам, но если такого нет, то существуют телеграм-чаты для начинающих, в которых вам всегда помогут.
Сильно не грузитесь, двигайтесь потихонечку.
Вопрос: Как очистить форму после выполнения?

Лучший ответ:
Для генерации id использую библиотечку node-uuid
Например: import { v4 } from 'node-uuid'
...
const myId = v4()
...

Худший ответ:
Сохраняйте изменение элементов формы в состоянии дочернего компонента, а потом просто отправляйте состояние и после очищайте его:function getDefaultState() {
	return {
		title: '',
		year: '',
		format: '',
		actors: ''
	};
}

export default React.createClass({
	handleFilmAdd() {
    this.props.onFilmAdd({
			id: 'some_id',
			...this.state
		});

		this.setState(getDefaultState());
  },

	handleChange(field, value) {
		this.setState({
			[field]: value
		});
	}

  render() {
    return (
    	<div>
       <input
        value={this.state.title}
				onChange={this.handleChange.bind(this, 'title')}
        placeholder='Title'
        ref='addTitle'
      />
      	<input
        value={this.state.year}
				onChange={this.handleChange.bind(this, 'year')}
        placeholder='Release Year'
        ref='addYear'
      />
        <input
        value={this.state.format}
				onChange={this.handleChange.bind(this, 'format')}
        placeholder='Format'
        ref='addFormat'
      />
      <textarea
	      value={this.state.actors}
				onChange={this.handleChange.bind(this, 'actors')}
	      placeholder='Actors'
	      ref='addActors'>
      </textarea>
      <button onClick={this.handleFilmAdd}>Add</button>
      </div>
    );
  }
});
Вопрос: Как упростить запрос с группировкой, максимальным значением и JOIN в MySQL?

Лучший ответ:
Попробуйте следующее:SELECT
  pd.product_id,
  d.name,
  d.discount_percent,
  d.discount_amount
FROM s_products_discount pd
JOIN s_discounts d ON pd.discount_id = d.id
WHERE 1
AND pd.product_id IN ('41987', '41988', '41989', '41990', '41991', '41992', '41993', '41994') # проверять список ид ДО более сложной проверки
AND d.priority = (
  SELECT MAX(sd.priority)
  FROM s_products_discount spd
  JOIN s_discounts sd on spd.discount_id = sd.id
  WHERE spd.product_id = pd.product_id
  AND sd.visible = 1
  AND sd.date_from <= '2018-05-05'
  AND sd.date_to >= '2018-05-05'
)
У меня только возник вопрос... А зачем везде LEFT JOIN? Разве в текущей задаче нужен именно он, а не просто join? Такое чувство, что left пишется просто по привычке.
В чем состояла оптимизация - вы строите временную таблицу, где к каждому продукту ищется максимальный доступный приоритет. Если представить, что у нас пол миллиона продуктов, вы хотим выбрать только десяток - все равно будет построена таблица по всем продуктам. Я же переместила подзапрос в where, где будет сравниваться приоритет для конкретного продукта. Судя по моим маленьким тестам, даже на малом количестве данных запрос не проигрывает, на большом количестве данных разница должна быть заметнее.

Худший ответ:
В подзапросе таблица s_products_discount  не нужна, можно вот так попробовать:SELECT pd.product_id,
       d.name,
       d.discount_percent,
       d.discount_amount
  FROM s_products_discount pd
  LEFT JOIN s_discounts     d
         ON d.id = pd.discount_id 
  LEFT JOIN (SELECT MAX(d.priority) as max_priority
               FROM s_discounts dd
              WHERE dd.id         = pd.discount_id
                AND dd.visible    = 1
                AND dd.date_from <= '2018-05-05'
                AND dd.date_to   >= '2018-05-05') pp 
         ON pp.max_priority = d.priority
 WHERE pd.product_id IN ('41987', '41988', '41989', '41990', '41991', '41992', '41993', '41994')
Вопрос: Как изменить данные из одной «утки» в другой?

Лучший ответ:
Зачем вообще в товаре свойство addedToCart?
Представьте, что у вас в приложении есть или будет пагинация. Вы перешли вперед-назад и загрузили товары заново. Ключи при этом будут потеряны.
Сделайте селекторы checkIsProductAddedToCartSelector и isProductAddedToCartSelector. Первый пусть возвращает функцию принимающую id товара и возвращающую true если товар найден в store корзины. Второй пусть принимает id товара и возвращает булево значение, если товар найден или не найден в store корзины. Используйте для этого reselect.
И добавляйте их в mapStateToProps в connect.
В списке можно вызывать так:const ProductsList = ({
  productsList,
  checkIsProductAddedToCart,
}) => (
  <ul>
    {productsList.map(product => (
      <Product
        addedToCart={checkIsProductAddedToCart(product.id)}
        product={product}
      />
    ))}
  </ul>
);

const mapStateToProps(state => ({
  productsList: productListSelector(state),
  checkIsProductAddedToCart: checkIsProductAddedToCartSelector(state),
}));

export default connect(mapStateToProps)(ProductsList);
В детализации так:const mapStateToProps((state, ownProps) => ({
  isAddedToCart: isProductAddedToCartSelector(state, ownProps),
}));

export default connect(mapStateToProps)(ProductDetails);
Примерные реализации селекторов:import { createSelector } from 'reselect';

const cartSelector = state => state.cart;

const cartProductsSelector = createSelector(
  cartSelector,
  cart => cart.products,
);

// возвращает функцию, принимающую id, которую можно использовать при построении списков
const checkIsProductAddedToCartSelector = createSelector(
  cartProductsSelector,
  products => id => products.some(product => product.id === id),
);

const productIdSelector = (_, props) => props.product.id;

// возвращает булево значение, важно чтобы в компоненте было свойство product
const isProductAddedToCartSelector = createSelector(
  cartProductsSelector,
  productIdSelector,
  (products, id) => products.some(product => product.id === id),
);

Худший ответ:
Можно в редьюсере каталога на экшен ADD_PRODUCT_TO_CART_SUCCESS менять состояние добавленного товара. Что то типа:case ADD_PRODUCT_TO_CART_SUCCESS:
  return {
    ...state,
    entities: {
       ...state.entities,
       [action.payload.productUid]: {
           ...state.entities[action.payload.productUid],
           addedToCart: true,
       }
    }
}
Вопрос: Не знаю с чего начать изучение программирования, есть языки подходящие начинающим?

Лучший ответ:
Python | Программируем на Python

Худший ответ:
Javascript сейчас в тренде, как на фронтэнде ( браузер + фреймворки ), так и на бэкэнде ( Node.js ). Полагаю, что эта тенденция продолжится. Поэтому посоветую книгу Ника Моргана "JavaScript для детей. Самоучитель по программированию", есть в сети. Для изучения достаточно браузера и любого текстового редактора. Плюсом будет знакомый, после С++ и Java, синтаксис.