Как работает ваш пример:
$('#button1') // — Находит все елементы по селектору, которые в данный момент уже загружены
.on('click', // На все найденные елементы навешывается обработчик события
function() {
alert('Hi!');
});
По большому счету, скрипт, который работает с участком страницы, должен запускаться ПОСЛЕ того, как этот участок страницы будет загружен (в коде html, должен быть выше javascript).
Конструкция
$(document).ready,
позволяет не заботится о том, где именно находится ваш скрипт. С её помощью вы как бы говорите "Запусти мой код, когда вся страница будет загружена". И не важно, где сам скрипт находится. Даже если он в шапке, и запускается раньше, чем загрузется непосредственно сам html — его выполнение будет отложено.