Свойство position
Свойство position позволяет сдвигать элемент со своего обычного места. Цель этой главы – не только напомнить, как оно работает, но и разобрать ряд частых заблуждений и граблей.
position: static
Статическое позиционирование производится по умолчанию, в том случае, если свойство position не указано.
Его можно также явно указать через CSS-свойство:
position: static;
Такая запись встречается редко и используется для переопределения других значений position .
Здесь и далее, для примеров мы будем использовать следующий документ:
Без позиционирования ("position: static"). Заголовок А тут - всякий разный текст.
. В две строки!
В этом документе сейчас все элементы отпозиционированы статически, то есть никак.
Элемент с position: static ещё называют не позиционированным.
position: relative
Относительное позиционирование сдвигает элемент относительно его обычного положения.
Для того, чтобы применить относительное позиционирование, необходимо указать элементу CSS-свойство position: relative и координаты left/right/top/bottom .
Этот стиль сдвинет элемент на 10 пикселей относительно обычной позиции по вертикали:
position: relative; top: 10px;
h2 Заголовок сдвинут на 10px вниз. Заголовок А тут - всякий разный текст.
. В две строки!
Координаты
Для сдвига можно использовать координаты:
- top – сдвиг от «обычной» верхней границы
- bottom – сдвиг от нижней границы
- left – сдвиг слева
- right – сдвиг справа
Не будут работать одновременно указанные top и bottom , left и right . Нужно использовать только одну границу из каждой пары.
Возможны отрицательные координаты и координаты, использующие другие единицы измерения. Например, left: 10% сдвинет элемент на 10% его ширины вправо, а left: -10% – влево. При этом часть элемента может оказаться за границей окна:
h2 Заголовок сдвинут на 10% влево. Заголовок А тут - всякий разный текст.
. В две строки!
Свойства left/top не будут работать для position:static . Если их всё же поставить, браузер их проигнорирует. Эти свойства предназначены для работы только с позиционированными элементами.
position: absolute
position: absolute;
Абсолютное позиционирование делает две вещи:
- Элемент исчезает с того места, где он должен быть и позиционируется заново. Остальные элементы, располагаются так, как будто этого элемента никогда не было.
- Координаты top/bottom/left/right для нового местоположения отсчитываются от ближайшего позиционированного родителя, т.е. родителя с позиционированием, отличным от static . Если такого родителя нет – то относительно документа.
- Ширина элемента с position: absolute устанавливается по содержимому. Детали алгоритма вычисления ширины описаны в стандарте.
- Элемент получает display:block , который перекрывает почти все возможные display (см. Relationships between „display“, „position“, and „float“).
Например, отпозиционируем заголовок в правом-верхнем углу документа:
h2 Заголовок в правом-верхнем углу документа. Заголовок А тут - всякий разный текст.
. В две строки!
Важное отличие от relative : так как элемент удаляется со своего обычного места, то элементы под ним сдвигаются, занимая освободившееся пространство. Это видно в примере выше: строки идут одна за другой.
Так как при position:absolute размер блока устанавливается по содержимому, то широкий Заголовок «съёжился» до прямоугольника в углу.
Иногда бывает нужно поменять элементу position на absolute , но так, чтобы элементы вокруг не сдвигались. Как правило, это делают, меняя соседей – добавляют margin/padding или вставляют в документ пустой элемент с такими же размерами.
Одновременное указание left/right , top/bottom
В абсолютно позиционированном элементе можно одновременно задавать противоположные границы.
Браузер растянет такой элемент до границ.
div 10px от границ
Выражения Javascript
Компьютерная программа — это набор инструкций, которые должен выполнить компьютер.
В языках программирования такие программные инструкции называются выражениями.
Программа на JavaScript — это набор программных выражений.
Пример:
var x, y, z; // Выражение 1 x = 5; // Выражение 2 y = 6; // Выражение 3 z = x + y; // Выражение 4
В HTML программа на JavaScript выполняется веб-браузером.
Выражения JavaScript
Выражения JavaScript состоят из: значений, операторов, операндов, ключевых слов и комментариев.
Выражение, приведенное в следующем примере, говорит браузеру, что нужно вывести строку «Привет!» внутри HTML элемента с идентификатором id=»demo»:
document.getElementById("demo").innerHTML = "Привет!";
Выражения в программе на JavaScript выполняются последовательно, друг за другом, в том порядке, в котором они написаны.
JavaScript программу (и JavaScript выражения) часто называют JavaScript кодом.
Точка с запятой ;
Точка с запятой (;) разделяет выражения JavaScript.
Добавляйте точку с запятой после каждого исполняемого выражения:
var a, b, c; // Декларирует три переменные a = 5; // Присваивает значение 5 переменной a b = 6; // Присваивает значение 6 переменной b c = a + b; // Вычисляет сумму значений переменных a и b и результат присваивает переменной c
При использовании точки с запятой, можно размещать несколько выражений на одной строке:
a = 5; b = 6; c = a + b;
В сети можно встретить Javascript программы, где точка с запятой не используется.
Действительно, использование точки с запятой в конце выражения не обязательно, но настойчиво рекомендуется.
Пробелы в JavaScript
JavaScript игнорирует множественные пробелы. Тем не менее, для улучшения читаемости кода вы можете по желанию добавлять пробелы в свой скрипт.
Следующие строки эквивалентны:
var person = "Петр"; var person="Петр";
Считается хорошей практикой добавлять пробелы до и после операторов ( = + — * / ):
var x = y + z;
Длина строки и перенос на новую строку
Для лучшей читаемости программисты часто избегают писать строки кода длиннее 80 символов.
Если выражение JavaScript получается слишком длинным, то его можно перенести на новую строку. Обычно это делают сразу после оператора:
document.getElementById("demo").innerHTML = "Привет!";
Блоки кода JavaScript
Выражения JavaScript могут группироваться в блоки кода. Это делается путем размещения группируемых выражений внутри фигурных скобок .
Блоки кода предназначены для определения выражений, выполняемых вместе.
Одно из мест где можно встретить выражения, сгруппированные в блоки, это функции JavaScript:
function myFunction()
Обычно для визуального выделения блоков кода перед сгруппированными выражениями ставят несколько пробелов.
Более подробно о функциях вы узнаете немного позже.
Ключевые слова JavaScript
Очень часто в выражениях JavaScript используются ключевые слова, которые приказывают JavaScript выполнить некие действия.
В следующей таблице представлены некоторые ключевые слова, о которых вы узнаете в этом учебнике:
| Ключевое слово | Описание |
|---|---|
| break | Прерывает цикл или проверку по команде switch |
| continue | Прекращает текущую итерацию цикла и продолжает выполнение со следующей итерации |
| debugger | Останавливает выполнение скрипта JavaScript и вызывает (если возможно) функцию отладки |
| do . while | Создает цикл с проверкой условия после каждой итерации |
| for | Создать цикл, указав начальное состояние, условие и операцию обновления состояния |
| function | Декларирует функцию |
| if . else | Выполняет тот или иной блок кода в зависимости от того, верно ли условие |
| return | Завершает функцию |
| switch | Сравнивает значение выражения с различными вариантами и при совпадении выполняет соответствующий код |
| try . catch | Реализует обработку ошибки при выполнении блока выражений |
| var | Декларирует переменную |
Ключевые слова зарезервированы за языком JavaScript. Эти слова нельзя использовать в качестве имен переменных или функций.
JavaScript: Функциональное Выражение vs. Объявление Функции
В JavaScript есть два способа создания функции: функциональное выражение и объявление функции. Мы обсудим когда использовать функциональное выражение, а когда объявление и объясним различия между ними.
Объявления функции использовались в течении долгого времени, но постепенно вытеснялись функциональными выражениями. Многие разработчики не уверены, когда использовать тот или иной метод объявления функции, поэтому в конечном итоге используют не тот.
Есть несколько ключевых различий между функциональными выражениями и объявлениями функций. Давайте подробнее рассмотрим эти различия, а также то, когда использовать в коде выражение или объявление функций.
function funcDeclaration()
return 'Объявление функции';
>
let funcExpression = function ()
return 'Функциональное выражение';
>
Что такое объявление функции
Объявление функции — это когда вы создаёте функцию и даёте ей имя. Вы объявляете имя функции, когда пишете ключевое слово function , за которым следует имя функции. Например:
function myFunction()
// делаем что-то
>;
Как видите, имя функции ( myFunction ) объявляется при создании функции. Это означает, что вы можете вызвать функцию до того, как она будет определена.
Пример объявления функции:
function add (a, b)
return a + b;
>;
Что такое функциональное выражение
Функциональное выражения — это когда вы создаёте функцию и назначаете её переменной. Функция анонимна, это означает, что у неё нет имени. Например:
let myFunction = function()
// делаем что-то
>;
Как видите, функция присваивается переменной myFunction . Это означает, что вы должны определить функцию, прежде чем сможете её вызвать.
Пример функционального выражения:
let add = function (a, b)
return a + b;
>;
Различия между функциональным выражением и объявлением
Есть несколько ключевых различий между функциональными выражениями и объявлениями функций:
- Объявления функций поднимаются, а выражения функций — нет. Это означает, что вы можете вызвать функцию до того, как она будет определена, но не можете сделать это с функциональным выражением.
- С функциональными выражениями вы можете использовать функцию сразу после её определения. При объявлении функции вам придётся ждать, пока весь сценарий не будет проанализирован.
- Функциональные выражения могут использоваться в качестве аргумента другой функции, но объявления функции — нет.
- Функциональные выражения могут быть анонимными, а объявления функции — нет.
JavaScript: Что такое hoisting
В JavaScript hoisting позволяет использовать функции и переменные до их объявления. В этой статье мы узнаем что такое hoisting, и как он работает.
www.dev-notes.ru
Понимание области видимости в функциональном выражении: различия в подъёме JavaScript
Как и в случае с оператором let , объявления функций поднимаются поверх основного кода.
Функциональные выражения не поднимаются. Это позволяет им сохранить копию локальных переменных из области, в которой они были определены.
Обычно вы можете использовать объявления функций и функциональные выражения взаимозаменяемо. Но бывают случаи, когда функциональные выражения приводят к более лёгкому для понимания коду без необходимости использования временного имени функции.
Как выбрать между выражением и объявлением
Итак, когда следует использовать функциональные выражения, а когда объявления функций?
Ответ зависит от ваших потребностей. Если вам нужна более гибкая функция или функция, которая не поднимается, тогда вам подойдёт функциональное выражение. Если вам нужна более читабельная и понятная функция, используйте объявление функции.
Как вы могли заметить, эти два синтаксиса похожи. Наиболее очевидная разница заключается в том, функциональные выражения анонимны, а объявления функций именованные.
Обычно вы используете объявление функции, когда вам нужно что-то, что не могут сделать функциональные выражения. Если вам не нужно делать ничего, что можно сделать только с помощью объявления функции, то лучше использовать функциональное выражение.
Используйте объявления функций, когда нужно создать рекурсивную функцию или когда нужно вызвать функцию перед её определением. Используйте функциональные выражения для более чистого кода, когда вам не нужно делать ни одну из этих вещей.
Преимущества объявлений функций
Есть несколько ключевых преимуществ объявления функций.
- Это может сделать код более читабельным. Если у вас длинная функция, присвоение имени может помочь отслеживать, что она делает.
- Объявления функций поднимаются — это означает, что они доступны до того, как будут определены в вашем коде. Это помогает, если нужно использовать функцию до её определения.
Преимущества функциональных выражений
Функциональные выражения также имеют свои преимущества.
- Они более гибкие, чем объявления функций. Вы можете создавать функциональные выражения и назначать их различным переменным, что может быть полезно, когда вам нужно использовать одну и ту же функцию в разных местах.
- Функциональные выражения не поднимаются, поэтому вы не можете использовать их до того, как они будут определены в вашем коде. Это помогает, если вы хотите убедиться, что функция используется только после её определения.
Когда выбирать объявление функции или функциональное выражение
В большинстве случаев легко понять, какой метод определения функции лучше всего подходит для ваших нужд. Эти рекомендации помогут вам быстро принять решение в большинстве ситуаций.
Используйте объявление функций когда:
- вам нужна более читаемая и понятная функция (например, длинная функция или та, которую вам нужно будет использовать в разных местах);
- анонимная функция вам не подойдёт;
- вам нужно создать рекурсивную функцию;
- вам нужно вызвать функцию до её определения.
Используйте функциональные выражения когда:
- вам нужна более гибкая функция;
- вам нужна функция, которая не поднимается;
- функция должна использоваться только тогда, когда она определена;
- функция анонимна или не нуждается в имени для последующего использования;
- вы хотите контролировать, когда функция выполняется, используя такие метода, как немедленно вызываемые функции ( IIFE );
- вы хотите передать функцию в качестве аргумента другой функции.
Тем не менее есть ряд случаев, когда гибкость функциональных выражений становиться мощным преимуществом.
Раскрытие функционального выражения: Различия в подъёме JavaScript
Есть несколько различных способов, которыми функциональные выражения становятся более полезными, чем объявления функций.
- Замыкания
- Аргументы других функций
- Немедленно вызываемое функциональное выражение (IIFE)
Создание замыкания с функциональными выражениями
Замыкания используются, когда вы хотите передать параметры функции до того, как эта функция будет выполнена. Хороший пример того, как это может вам помочь — циклический просмотр NodeLest .
Замыкание позволяет сохранить другую информацию, такую как индекс, в ситуациях, когда эта информация недоступна после выполнения функции.
function tabsHandler(index)
return function tabClickEvent(evt)
// Выполняем разные вещи с tab.
// Доступ к индексной переменной можно получить отсюда.
>;
>
let tabs = document.querySelectorAll('.tab'),
i;
for (i = 0; i tabs.length; i += 1)
tabs[i].onclick = tabsHandler(i);
>
Присоединённые обработчики событий выполняются позже (после завершения цикла), поэтому необходимо замыкание для сохранения соответствующего значения цикла for .
// Плохой код демонстрирующий, почему необходимо замыкание
let i;
for (i = 0; i list.length; i += 1)
document.querySelector('#item' + i).onclick = function doSomething(evt)
// Делаем что-то с item i
// Но к моменту выполнения этой функции значения i всегда равно list.length
>
>
Легче понять, почему возникает проблема, если извлечь функцию doSomething из цикла for .
// Плохой код демонстрирующий, почему необходимо замыкание
let list = document.querySelectorAll('.item'),
i,
doSomething = function (evt)
// Делаем что-то с item i
// Но к моменту выполнения этой функции i уже не то, что было в цикле.
>;
for (i = 0; i list.length; i += 1)
item[i].onclick = doSomething;
>
Решение состоит в том, чтобы передать индекс в качестве аргумента внешней функции, чтобы она могла передать это значение внутренней функции. Вы часто будете видеть функции обработчики, используемые для организации информации, необходимой внутренней возвращающей функции.
// The following is good code, demonstrating the use of a closure
let list = ['item1', 'item2', 'item3'],
i,
doSomethingHandler = function (itemIndex)
return function doSomething(evt)
// now this doSomething function can retain knowledge of
// the index variable via the itemIndex parameter,
// along with other variables that may be available too.
console.log('Doing something with ' + list[itemIndex]);
>;
>;
for (i = 0; i < list.length; i += 1)
list[i].onclick = doSomethingHandler(i);
>
Передача функционального выражения в качестве аргумента
Функциональные выражения могут быть переданы непосредственно в функции без необходимости присваивания промежуточной временной переменной.
Чаще всего вы будете видеть их в виде анонимных функций. Вот знакомый многим пример функционального выражения jQuery:
$(document).ready(function ()
console.log('An anonymous function');
>);
Функциональное выражение также используется для обработки элементов массива при использовании таких метода, как forEach() .
Они не должны быть безымянными анонимными функциями. Хорошая идея — давать имя функциональному выражению, это поможет выразить для чего предназначена функция и поможет при отладке:
let productIds = ['12356', '13771', '15492'];
productIds.forEach(function showProduct(productId)
.
>);
Немедленно вызываемые функциональные выражения ( IIFE )
IIFE помогают предотвратить влияние ваших функций и переменных на глобальную область видимости.
Все свойства внутри попадают в область действия анонимно функции. Это распространённый шаблон проектирования для предотвращения появления в вашем коде неожиданных и нежелательных побочных эффектов.
Также они используются в качестве шаблона модуля для размещения кодов блока в секциях, которые легко поддерживать.
Простой пример IIFE:
(function ()
// код здесь
>());
. который при использовании в качестве модуля может привести к облегчению сопровождения кода.
let myModule = (function ()
let privateMethod = function ()
console.log('A private method');
>,
someMethod = function ()
console.log('A public method');
>,
anotherMethod = function ()
console.log('Another public method');
>;
return
someMethod: someMethod,
anotherMethod: anotherMethod
>;
>());
Заключение
Как вы убедились, функциональные выражения не сильно отличаются от объявлений функции, но они часто могут привести к более чистому и читабельному коду.
Широкое использование делает их неотъемлемой частью набора инструментов каждого разработчика. Используете ли вы функциональные выражения каким-либо интересным способом не упомянутом в статье?
<> + <>. Почему такой результат?

P.S: Знал бы английский и умел бы хорошо понимать документация ECMAScript, я бы не спрашивал.
Отслеживать
Виталик Черный
задан 23 окт 2017 в 13:11
Виталик Черный Виталик Черный
1,476 1 1 золотой знак 11 11 серебряных знаков 35 35 бронзовых знаков
Это где это у вас так получилось? В моём Firefox <> + <> даёт именно NaN
23 окт 2017 в 13:12
23 окт 2017 в 13:13
А у меня вот так i.stack.imgur.com/p3xQw.png 🙂
23 окт 2017 в 13:13
@andreymal я и в опере тестил. скрин залил, там вообще ересь.
23 окт 2017 в 13:17
Это же классический WAT :destroyallsoftware.com/talks/wat
– user177221
31 окт 2017 в 12:32
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
Основной поток кода — это место, которое не является частью выражения.
Вот моменты языка, которые могут быть размещены только в основном потоке кода:
- function declaration (отличается от function expression)
- блок кода (отличается от объекта)
- метки (отличаются от имён свойств)
- все синтаксические конструкции языка: if, else, try, var и т. д.
Если есть две похожие конструкции, одна из которых может существовать только в основном потоке, то именно этот критерий будет использоваться для их различения: если код размещён в основном потоке кода, то выбирается соответствующая конструкция, а если в выражении, то другая.
Что касается записи <>+<> , то в случае основного потока кода её значение обычно вообще никуда не попадает, хотя и выводится в REPL-средах как результат. Первая фигурная скобка означает открытие блока кода, затем вторая его заканчивает. Потом попадается плюс — левого операнда у нас нет, значит он унарный. Мы уже находимся в выражении. Фигурная скобка в выражении начинает объект. Следующая — заканчивает объект. Получается +<> , затем +»[object Object]» и NaN .
В случае же с console.log сам вызов функции образует выражение. Поэтому первая пара скобок превращается в объект, а вся сумма после приведения типов в конкатенацию строк.
Единственный способ (по крайней мере в ES2018-) получить в коде это передать строку с кодом в eval.
function run(code) < try < console.log(eval(code)) >catch(e) < console.log(e.name + " " + e.message) >> run(' + ') run('( + )') // круглые скобки run(' + ') // метка! run(' + ') // ошибка - метка не может быть вне основного потока run(' + ') // `;`, а не `,` - две метки
Что касается консоли хрома — судя по всему они сделали умное определение, является ли нечто в фигурных скобках объектом или куском кода. Причём, предпочтение отдаётся объекту. Думаю, это сделано для большего удобства, что если ты вводишь выражение в консоль, то ты хочешь результат выражения, который ты не получишь в основном потоке кода. Но стоит заметить, что эта штука в консоли работает только для top-level-кода (да и то не всегда), и не распространяется на вложенный код:

А логика угадывания не такая уж сложная: если код начинается на < и заканчивается на >, не являющуюся частью однострочного комментария, то он в первую очередь пытается распарсить его как выражение, а если не получается, то как statement: