Основы liquid
Основы liquidLiquidhub
Теги
Теги управляют логикой шаблонов. При их помощи вы можете организовывать циклы и логику ветвления.
В liquid для тегов существует два типа разделителей:
- {{ code }}
- {% code %}
Liquid
Привет, {{ 'Вася' }}!
>> Привет, Вася!
{{ account.title }}
>> Название интернет-магазина из настроек аккаунта.
{% for product in collections.all.products %}
<p>{{ product.title }}</p>
{% endfor %}
>> <p>Имя товара 1</p>
>> <p>Имя товара 2</p>
>> <p>Имя товара 3</p>
{% assign is_visible = false %}
{% if is_visible %}
Показать
{% else %}
Скрыть{% endif %}
>> Скрыть
{% for i in (1. .4) %}
{% cycle 'odd', 'even' %} /
{% endfor %}
>> odd / even / odd / even /
{% include 'footer' %}
>> Содержимое сниппета «footer»
Фильтры
Для преобразования выходных данных можно использовать фильтры. Фильтры это обычные функции.
Первый аргумент пишется слева от имени фильтра и отделяется от него символом «|» (труба).
Результатом работы фильтра является преобразованный элемент, который подставляется в это место текста.
Исходные данные, например значения переменных, которые являлись аргументом фильтра, сохраняют своё прежнее значение.
See the Pen Liquid filters on CodePen.Операторы сравнения
В Liquid есть доступ ко всем логическим операторам и операторам сравнения.
Оператор | Назначение |
---|---|
== | равно |
!= | не равно |
> | больше |
< | меньше |
>= | больше или равно |
<= | меньше или равно |
or | Логическое ИЛИ |
and |
Новости и статьи
Обновления платформы
Смотреть новости
Документация по API insales
API для написания интеграций
Перейти на сайт документации
Разработка приложений
Пошаговая документация
Подробнее
Партнерская программа
Станьте партнером InSales
Подробнее о программе
Товар добавлен в корзину
Оформить заказ
Заказать обратный звонок
Cогласиться на обработку персональных данных
Включите в вашем браузере JavaScript!
Интересный случай Null >= 0 / СоХабр
Перевод https://blog.
campvanilla.com/javascript-the-curious-case-of-null-0-7b131644e274Составляя заметки для ускоренного курса по JavaScript, который я должен был преподать нескольким своим коллегам, я столкнулся с довольно интересным сценарием с null
и операторами сравнения.
null > 0; // false null == 0; // false null >= 0; // true
Подождите… подождите… чего? Это бессмыслица какая то!
как значение не может быть больше, чем 0
, не может быть равно 0
, но при этом быть больше или равно 0
Хотя я сначала это убрал, так как Javascript был Javascript, со всеми его причудливостями, но меня это заинтриговало. Имело ли это какое-то отношение к типу null
и тому, как он обрабатывается или с тем как выполняются проверки сравнения отношений?
Поэтому я попытался найти основную причину этого и начал анализировать через единственный источник истины для Javascript —
Алгоритм абстрактного реляционного сравнения
Давайте сделаем первую проверку.
null > 0; // false
Согласно спецификации, операторы сравнения >
и <
отправляют утверждение через алгоритм, называемый алгоритмом абстрактного реляционного сравнения, чтобы выяснить, является ли утверждение true
или false
.
1. Вызов ToPrimitive (x, номер подсказки). 2. Вызов ToPrimitive (y, номер подсказки). 3. Если тип (результат (1)) является String и тип (результат (2)) является String, перейдите к шагу 16. (Обратите внимание, что этот шаг отличается от шага 7 в алгоритме для оператора сложения + при использовании 'и' вместо 'или'.) 4. Вызов ToNumber (Результат (1)). 5. Вызов ToNumber (Результат (2)). 6. Если результатом (4) является NaN, вернет значение undefined. 7. Если результатом (5) является NaN, вернет значение undefined. 8. Если результат (4) и результат (5) совпадают с числовым значение, вернет значение false. 9. Если результат (4) равен +0, а результат (5) равен -0, вернет значение false. 10. Если результат (4) равен -0, а результат (5) равен +0, вернет значение false. 11. Если результат (4) + ∞, вернет false. 12. Если результат (5) + ∞, вернет true. 13. Если результат (5) -∞, вернет false. 14. Если результат (4) -∞, вернет true. 15. Если математическое значение результата (4) меньше математического значения результата (5) ---- обратите внимание, что эти математические значения являются как конечными, так и не равными нулю - возвратит true. В противном случае вернет false. 16. Если результат (2) является префиксом результата (1), вернет false. (String значение p является префиксом строкового значения q, если q может быть результатом объединения p и некоторой другой строки r. Обратите внимание, что любая строка является префиксом самой, поскольку r может быть пустой строкой.) 17. Если результат (1) является префиксом результата (2), вернет true. 18. Пусть k - наименьшее неотрицательное целое число, такое, что символ в позиции k в результате (1) отличается от символа в позиции k в результате (2).(Там должен быть такой ak, поскольку ни одна строка не является префиксом другого.) 19. Пусть m - целое число, которое является значением кодовой точки для символа в позиции k в результата (1). 20. Пусть n - целое число, которое является значением кодовой точки для символа в позиции k в результата (2). 21. Если m < n, вернет true. В противном случае вернет false.
Давайте рассмотрим этот алгоритм с нашим утверждением — null > 0
.
Шаги 1 и 2 просят нас вызвать ToPrimitive()
null
и 0
соответственно, чтобы преобразовать эти значения в свои примитивные типы значений (например, Numberи String). Преобразования ToPrimitive
следует из этой таблице.Тип ввода | результат |
---|---|
Undefined | Нет конверсии |
Null | Нет конверсии |
Boolean | Нет конверсии |
Number | Нет конверсии |
String | Нет конверсии |
Object | Вернет значение по умолчанию для объекта. Значение по умолчанию для объекта извлекается, вызывая внутренний метод [[DefaultValue]] объекта, передавая необязательную подсказку PreferredType |
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, | … |
Следуя таблице, наши
и 0
, не подвергаются никакому преобразованию.
Так, Шаг 3, не относится к нам, поэтому мы можем игнорировать его и двигаемся дальше. На шагах 4 и 5 нам нужно преобразовать правую и левую часть в тип Number. Преобразование в Number в соответствии с этой таблицей.
Тип ввода | результат |
---|---|
Undefined | NaN |
Null | +0 |
Number | Нет конверсии |
Boolean | Результат равен 1, если аргумент истинен. Результат равен +0, если аргумент ложный. |
… | … |
( Я пропустил String
и Object
из таблицы, поскольку они имеют более сложное преобразование, и не имеют отношения к нам в любом случае. Если вам это интересно, вы можете найти их здесь.)
null
преобразуется в +0
a 0
остается 0
. Ни одно из значений NaN
так что позволяют нам пропустить шаги 6 и 7. На шаге 8 мы должны остановиться. +0
является равным 0
, и алгоритм возвращает false
. Следовательно,
null > 0; // false а также null < 0; // также false
Алгоритм сравнения абстрактного равенства
Давайте рассмотрим следующую проверку.
null == 0; // false
Это довольно интересно.
Оператор ==
запускает утверждение через Аннотация Равенства алгоритм сравнения, и возвращает true
или false
.
1. Если тип ( x ) отличается от типа ( y ), перейдите к шагу 14. 2. Если тип ( x ) не определен, вернет true. 3.Если тип ( x ) имеет значение Null, вернет true. 4. Если тип ( x ) не является числом, перейдите к шагу 11.5. Если ( x ) является NaN, вернет false . 6. Если ( y ) - NaN, вернет false . 7. Если ( x ) - это то же числовое значение, что и ( y ) , вернет true . 8. Если ( x ) равно +0, а ( y ) равно -0 , вернет true . 9. Если ( x ) равно -0 и ( y ) равно +0 , вернет true . 10. Вернет значение false. 11.Если тип ( x ) является String, тогда вернет true, если ( x ) и ( y ) - это точно такая же последовательность символов (одинаковая длина и одинаковые символы в соответствующих позициях). В противном случае вернет false. 12. Если тип ( x ) является Boolean, вернет true, если ( x ) и ( y ) оба true или оба false. В противном случае вернет false . 13. Вернет true, если ( x ) и ( y ) относятся к одному и тому же объекту или относятся к объектам, соединенным друг с другом (см. 13.1.2 ). В противном случае вернет false. 14. Если ( x ) равно null, а y не определено, вернет true . 15. Если ( x ) не определено и y равно null, вернет true . 16.Если тип ( x ) является Number и тип ( y ) является String, вернет результат сравнения ( x ) == ToNumber ( y ). 17.Если тип ( x ) является String и тип ( y ) является Number, вернет результат сравнения ToNumber ( x) == ( y ) . 18. Если тип ( x ) является Boolean, вернет результат сравнения ToNumber ( x) == ( y ). 19. Если тип ( y ) булев, вернет результат сравнения x == ToNumber ( y ). 20.Если Type ( x ) является либо String, либо Number и тип ( y ) является Object, вернет результат сравнения ( x ) == ToPrimitive ( y ). 21.Если тип ( x ) является Object и тип ( y ) является либо String, либо Number, вернет результат сравнения ToPrimitive ( x) == ( y ) . 22. Вернет значение false.
Оценивая равенство null
и 0
, мы сразу переходим от шага 1 к шагу 14, поскольку типы не совпадают. Удивительно, но шаги 14 до 21, также не относятся к нам, так как тип ( х ) есть null
. Наконец, мы достигнем шага 22, и значение false
возвращается по умолчанию !
Следовательно,
null == 0; // false
Оператор больше либо равно ( >= )
И теперь мы добираемся до последней проверки.
null >= 0; // true
И вот тут спека полностью поразила меня. На очень высоком уровне реляционный оператор >=
оценивает так
если null < 0 является false , тогда null >= 0 является true
Таким образом
null >= 0; // true
И это, если честно, имеет смысл. Математически, если у нас есть два числа, x
и y
, если x
не меньше y
, то x
больше либо равно y
.
Я предполагаю, что это сделано, чтобы оптимизировать оценку утверждения. Пожалуй если проверить что x
больше y
, и если это не так, если x
равно y
, тогда вы можете выполнить только одну оценку - это x
меньше чем y
, а затем использовать этот результат для оценки.
(Если вас интересуют фактические шаги, выполняемые для оператора >=
, вы можете найти их здесь . )
Какая банальная была эта проблема, поиск ответа привел на некоторые интересные выводы об языке. Надеюсь, эта статья сделает то же самое для вас.
Качество кода. Имеет ли смысл использовать == в JavaScript?
Как профессиональный математик, я вижу в Javscript операторе одинаковости ==
(также называемом «абстрактное сравнение», «свободное равенство») попытку построить отношение эквивалентности между сущностями, которое включает в себя рефлексивность, симметричность и транзитивность. К сожалению, два из этих трех фундаментальных свойств не работают:
A == A
может быть ложным, например.
NaN == NaN // ложь
A == B
и B == C
вместе не означают A == C
, т.е.
'1' == 1 // правда 1 == '01' // правда '1' == '01' // ложь
Выживает только симметричное свойство:
A == B
подразумевает B == A
, нарушение которого в любом случае, вероятно, немыслимо и приведет к серьезному бунту 😉
Почему отношения эквивалентности имеют значение?
Потому что это самый важный и распространенный тип отношений, подтвержденный многочисленными примерами и приложениями. Наиболее важным приложением является разложение сущностей на классы эквивалентности, что само по себе является очень удобным и интуитивно понятным способом понимания отношений. А неэквивалентность приводит к отсутствию классов эквивалентности, что, в свою очередь, ведет к общеизвестному отсутствию интуитивности и ненужной сложности.
Почему такая ужасная идея писать
==
для отношения неэквивалентности?Потому что это нарушает наше знакомство и интуицию, поскольку буквально любое интересное отношение подобия, равенства, конгруэнтности, изоморфизма, тождества и т. д. является эквивалентностью.
Преобразование типов
Вместо того, чтобы полагаться на интуитивную эквивалентность, JavaScript вводит преобразование типов:
Оператор равенства преобразует операнды, если они не одного типа, а затем применяет строгое сравнение.
Но как определяется преобразование типов? Через набор сложных правил с многочисленными исключениями?
Попытка построения отношения эквивалентности
Логические значения. Очевидно, что true
и false
не совпадают и должны относиться к разным классам.
Номера. К счастью, равенство чисел уже четко определено, при котором два разных числа никогда не принадлежат одному и тому же классу эквивалентности. В математике то есть. В JavaScript понятие числа несколько деформировано из-за присутствия более экзотического числа 9.0003-0 , Бесконечность
и -Бесконечность
. Наша математическая интуиция подсказывает, что 0
и -0
должны быть в одном классе (на самом деле -0 === 0
равно true
), тогда как каждая из бесконечностей является отдельным классом.
Числа и логические значения. Учитывая числовые классы, куда мы поместим логические значения? false
становится подобным 0
, тогда как true
становится подобным 1
, но никакое другое число:
правда == 1 // правда истина == 2 // ложь
Есть ли логика в том, чтобы поставить true
вместе с 1
? По общему признанию, 1
различимы, но -1
тоже. Лично я не вижу смысла конвертировать true
в 1
.
И еще хуже:
true + 2 // 3 правда - 1 // 0
Таким образом, true
действительно преобразуется в 1
среди всех чисел!
Это логично? Это интуитивно понятно? Ответ оставлен в качестве упражнения 😉
А как насчет этого:
1 && true // true 2 && правда // правда
Единственное логическое значение x
, где x && true
равно true
равно x = true
. Что доказывает, что и 1
, и 2
(и любое другое число, кроме 0
) преобразуются в true
! Это показывает, что наше преобразование не соответствует другому важному свойству — биекции. Это означает, что два разных объекта могут быть преобразованы в один и тот же. Что само по себе не должно быть большой проблемой. Большая проблема возникает, когда мы используем это преобразование для описания отношения «одинаковости» или «неполного равенства» того, что мы хотим назвать. Но ясно одно — это не будет отношение эквивалентности и не будет интуитивно описано через классы эквивалентности.
Но можем ли мы сделать лучше?
По крайней мере, математически — определенно да!
Простое отношение эквивалентности между логическими значениями и числами может быть построено только с ложными
и 0
, принадлежащими к одному и тому же классу. Таким образом, false == 0
будет единственным нетривиальным свободным равенством.
Как насчет строк?
Мы можем обрезать строки от пробелов в начале и конце для преобразования в числа, также мы можем игнорировать нули впереди:
'000 ' == 0 // true '0010' == 10 // верно
Итак, мы получаем простое правило для строки — обрезать пробелы и нули впереди. Либо мы получаем число, либо пустую строку, и в этом случае мы конвертируем в это число или ноль. Или мы не получаем число, и в этом случае мы не конвертируем и не получаем нового отношения.
Таким образом, мы действительно могли бы получить идеальное отношение эквивалентности для всего набора логических значений, чисел и строк! За исключением того, что. .. дизайнеры JavaScript явно имеют другое мнение:
' ' == '' // false
Таким образом, две строки, обе из которых преобразуются в 0
, внезапно оказались непохожими! Почему или почему? По правилу строки приблизительно равны именно тогда, когда они строго равны! Как видим, это правило не только нарушает транзитивность, но и является избыточным! Какой смысл создавать еще один оператор ==
, чтобы сделать его строго идентичным другому ===
?
Заключение
Нечеткий оператор равенства ==
мог бы быть очень полезен, если бы он подчинялся некоторым фундаментальным математическим законам. Но поскольку это, к сожалению, не так, его полезность страдает.
Triple Equals против Double Equals в JavaScript
2 января 2020 г.
В JavaScript технически существует 4 различных способа сравнения двух значений. Двумя наиболее распространенными способами являются оператор ==
и оператор ===
, также известный как абстрактное сравнение равенства и строгое сравнение равенства .
Строгое равенство с
===
Учитывая 2 значения x
и y
, вот как JavaScript проверяет, является ли x === y
:
- Проверьте типы
x
иy
. Если они разных типов, вернитеfalse
. - Если
x
иy
являются числами, сначала проверьте, являются лиx
илиy
NaN
, и вернитеfalse
, если этоNaN
. Если обаx
иy
равны+0
или-0
, вернутьtrue
. В противном случае проверьте, совпадают ли они. - Если
x
иy
оба равныnull
или обаundefined
, вернутьtrue
. - Если
x
иy
являются логическими значениями, обеими строками или обоими символами, сравните их по значению. - Если
x
иy
являются объектами, возвращайте значение true тогда и только тогда, когда они ссылаются на один и тот же объект.
Короче говоря, вот важные детали ===
:
- Без неявного приведения типов.
===
не вызываетvalueOf()
или делает что-либо еще, чтобы попытаться преобразовать объекты в примитивы. - Нет значения
=== NaN
. Вы не должны использовать===
для проверкиNaN
, вместо этого используйтеNumber.isNaN()
. - Сравнение объектов по ссылке — два разных объекта могут содержать одни и те же ключи, но
===
все равно скажет, что они разные.
const obj1 = {ответ: 42}; const obj2 = {ответ: 42}; объект1 === объект2; // ложь
Абстрактное равенство с
==
Оператор ==
использует более сложный алгоритм сравнения абстрактного равенства, чтобы сравнить, равны ли x
и y
. Вот краткий обзор:
- Если
x
иy
одного типа, проверьте,x === y
. - Если
x
иy
оба равныnull
илиundefined
, вернутьtrue
. - Если
x
— число, аy
— строка, преобразуйтеy
в число, а затем сравните, используя===
. Точно так же, еслиx
— логическое значение или строка, аy
— число, преобразуйтеx
в число. - Если
x
илиy
является логическим значением, преобразуйте другое значение числа и сравните их. - Если
x
— объект, аy
— символ, строка или число, попробуйте преобразоватьx
к примитиву с использованиемvalueOf()
, а затем сравнить с использованием===
.
Абстрактное сравнение на равенство отвечает за многие странные пограничные случаи, которыми так славится JavaScript.
' ' == 0; // истинный '' == ложь; // истинный ({ valueOf: () => 42 }) == 42; // истинный ({ valueOf: () => 0 }) == false; // true
В общем, вы должны всегда использовать ===
, а не ==
, если вы не уверены
ты знаешь, что делаешь.