Заметьте, я и не говорил про спецификацию, я сказал про JS движки (V8 / Spider Monkey / etc.) и их оптимизацию такого поведения, что я не уверен, что подобное использование length не деоптимизирует байт код.
Исходя из поста, знание основ любого языка — признак профессионализма.
1. Очистка или усечение массива
А за такое можно сразу гнать из профессии. Мало того, что это, мягко скажем, необычное применение для length, это, предполагаю, может подгадить в плане оптимизации кода JS движком. Не говоря уж о том, что JS не требует ручного управления памятью.
4. Использование диапазонов значений в операторе switch
Во-первых, как уже было сказано выше, Cookie — ~4kB т.е. 4k char. В среднем, я не использовал JWT токены длинее 2k символов, но это не показатель, и ваш JWT может быть и в 8kB.
Во-вторых, cookie постоянно гоняются по сети, даже если вы этого не хотите (fetch и XMLHttpRequest не в счет, там по умолчанию false).
Вы абсолютно правы, что язык должен в первую очередь быть инструментом, а не целью. Но в большинстве языков: Python — input(), C — getchar(), Ruby — gets, инпут — это строка.
Так и в JS, input Dom node — содержит исключительно строки.
(простите, опечатался, не "a", а конечно же "x" станет числом тоже).
И в целом то, это проблема не JS, а вообще динамических языков, и языков с хоть чуть-чуть возможностью переопределять операторы или (и) неявно приводить типы.
# Python
>>> "5" * 10 + "8"
'55555555558'
Т.е. тут вопрос скорее к невнимательности. И тут TS или Flow, бы решили эту проблему (ну или попытались :) ).
Ну и сами вы себе злой буратино. Зная, что в JS такое поведение, и что input value — это всегда строка, кто мешает вам, опять же зная, что вы будете производить мат. операции над этим инпутом, самому сконвертировать.
const a = 0.1;
const x = +document.querySelector('input[name="x"]').value; // Вот теперь это число
const y = +document.querySelector('input[name="y"]').value; // И это тоже
console.log(x - a * y)
Хотя parseInt(n, 10) все-же более наглядно и конвертирует исключительно в десятичное число (т.к. +'0xFF' === 255).
По-хорошему, нужно x и y сконвертировать в число в момент присвоения
С чего бы это? Инпут хранит исключительно значение как строку, а если вы про input[type="number"] — то это не имеет никакого отношения к JS, это лишь валидация пользовательского инпута, как и type="email", а в JS это приходит как обычная DOMString.
Не совсем понимаю за что вас минусуют. Если вы не против, я добавлю комментарии к вашему коду, что-бы читателям стало понятно.
Для начала, это абсолютно валидный код с точки зрения C.
#define директива — это по-сути замена во время компиляции найденого токена (или вызова) на его значени. В случае выше, любая найденная a будет заменена на (__COUNTER__+1)
__COUNTER__ — это "магическое" макро значение, как и __FILE__, __LINE__, или __FUNCTION_. И в C / C++ эти значения опять же заменяются на этапе компиляции (см. выше). Сам же __COUNTER__ "магичен" из-за того, что при каждом новом вызове, он будет инкриментировать свое значение (от 0).
В итоге выражение (__COUNTER__+1) станет (0+1), затем (1+1), затем (2+1).
И весь код будет выглядеть так:
// Т.к. `include` тоже макрос, тут будет содержимое этого файла.
int main(void) {
if ((0+1) == 1 && (1+1) == 2 && (2+1) == 3) printf("123123123");
return 0;
}
А дальше все еще круче, если кому интересно, компилятор просто схлопнет (оптимизирует) константные выражения, и на выходе останется:
// Т.к. `include` тоже макрос, тут будет содержимое этого файла.
int main(void) {
printf("123123123");
return 0;
}
А что, если злобный админ поставит прокси перед /api/signin и будет писать не захешированные пароли (а напомню, они именно так по сети гуляют) в файлик?
И опять же, см. пункт с ресетом пароля, если он есть, то вы и так сможете получить письмо.
Но нужно еще продумать о безопасность этого подхода, т.к. хранить только email в клиентской сессии, вообще не безопасно, нужно тогда возвращать какой-нибудь секрет от запроса, сгенерированный бэком, а также хранить его в sign_in_requests таблице.
С хранением на бэке, примерна такая-же история, нужно будет записывать guid сессии (cookie-based сессии) в таблицу sign_in_requests, и опять же сверять при рефреше сочетание email + secret.
Если я вас правильно понял, вы хотите, чтобы страница (с которой отправлен запрос) сама перезагрузилась, когда вы перейдете по ссылке из письма. Идея хорошая, но тут может появиться излишние затраты либо на Long polling, либо на полноценный Web socket (запросы по таймаута — зверство, поэтому я их не рассматриваю). Но этот вариант может решить проблему с телевизорами / IoT'ами.
Можно сделать менее красивый, но и менее затратный вариант: запоминать email на который выслали письма, а после ручного рефреша страницы (или перехода на другую страницу) проверять, перешел ли пользователь по ссылке из письма и окончательно авторизовать его. Т.е. получается такая двух этапная авторизация, на первом шаге мы просто записали email в переменную сессии (localstorage / cookie / backend session), а после подтверждения активировали эту сессию.
Использование внешнего сервиса — это само по себе риск, даже в не самых критичных частях системы. Вы просто никак не можете работать с этим риском и влиять на него, особенно если это крупные сервисы типа mail.ru/gmail.com/
А что вам в предложенной схеме мешает использовать свой почтовый сервер, если вы не доверяете гуглу?
в совокупности вы получаете весьма нехилый риск с которым всеже вполне можно смириться в некритичных частях системы, однако авторизацию к таковым отнести не получится. И тут уж надо сделать так чтобы работало железобетонно, а если сломалось — то можно было починить, а не зависеть от того, что кто-то когда-то возможно исправит.
К сожалению, я склонен больше верить в то, что у сайта с "котиками" будет все плохо, нежели у Yandex / Google / Mail.
Практически все, если не все, проекты использующие oauth крупных сервисов для авторизации дублируют его возможностью классической авторизации, и это не просто от того, что могут — поверьте.
А почему в предложено выше варианте они не могут сосуществовать? Вы можете позволить пользователю самостоятельно сделать выбор чем он хочет пользоваться: Oauth / Email + Pass / Email.
Если же вы боитесь, что почту могут своровать, и тогда пользователь потеряет доступ и к вашему сервису, так и с паролем (на вашей стороне) не многое поменяется (как минимум — ресет пароля на почту).
Использовать телефон (СМС) гораздо доже и менее безопасно, чем почту.
А если предположить, что номер телефона может утечь, то начнется спам. А вот спам на телефон в разы более мерзкий, чем на email. Если у email сервисов уже отлажены методы борьбы со спамом, то вот у телефонов все плачевно, будете получать звонки от "пирамид" с разных номеров.
Заметьте, я и не говорил про спецификацию, я сказал про JS движки (V8 / Spider Monkey / etc.) и их оптимизацию такого поведения, что я не уверен, что подобное использование length не деоптимизирует байт код.
Касаемо спеки, да, данное поведение в ней явно прописано.
Исходя из поста, знание основ любого языка — признак профессионализма.
А за такое можно сразу гнать из профессии. Мало того, что это, мягко скажем, необычное применение для
length
, это, предполагаю, может подгадить в плане оптимизации кода JS движком. Не говоря уж о том, что JS не требует ручного управления памятью.А почему нельзя было через
if/else
?Во-первых, как уже было сказано выше, Cookie —
~4kB
т.е.4k char
. В среднем, я не использовал JWT токены длинее 2k символов, но это не показатель, и ваш JWT может быть и в 8kB.Во-вторых, cookie постоянно гоняются по сети, даже если вы этого не хотите (
fetch
иXMLHttpRequest
не в счет, там по умолчаниюfalse
).Да, т.к.
document.getElementById('layer1').style.opacity
— это строка, а не число.И формально, это равносильно этому:
Но тут уже важно понимание дела, т.е. TS не знает, хотите ли вы добавить символы в строку, или сложить числа.
И Flow сделает то-же самое: https://flow.org/try/#0DYUwLgBAhhC8EHICMCDcAodMDU8BMG6AxgPYB2AziaAHTAkDmAFFAJSoQD0ncAfBEjxA
Тут трудно не согласиться (я об это тоже сказал чуть выше). Но мы все-же говорим в контексте JS.
Собственно, надеюсь, я правильно понял вашу позицию. TS действительно крутой :).
Вы абсолютно правы, что язык должен в первую очередь быть инструментом, а не целью. Но в большинстве языков: Python —
input()
, C —getchar()
, Ruby —gets
, инпут — это строка.Так и в JS, input Dom node — содержит исключительно строки.
Справедливости ради, конечно же не все динамические языки одновременно и слабо типизированы, но надеюсь вы поняли, о чем я.
(простите, опечатался, не "
a
", а конечно же "x
" станет числом тоже).И в целом то, это проблема не JS, а вообще динамических языков, и языков с хоть чуть-чуть возможностью переопределять операторы или (и) неявно приводить типы.
Т.е. тут вопрос скорее к невнимательности. И тут TS или Flow, бы решили эту проблему (ну или попытались :) ).
И нет, "
a
" — не останется строкой, т.к. "-
" тоже кастует в NumberНу и сами вы себе злой буратино. Зная, что в JS такое поведение, и что input value — это всегда строка, кто мешает вам, опять же зная, что вы будете производить мат. операции над этим инпутом, самому сконвертировать.
Хотя
parseInt(n, 10)
все-же более наглядно и конвертирует исключительно в десятичное число (т.к.+'0xFF' === 255
).С чего бы это? Инпут хранит исключительно значение как строку, а если вы про
input[type="number"]
— то это не имеет никакого отношения к JS, это лишь валидация пользовательского инпута, как иtype="email"
, а в JS это приходит как обычнаяDOMString
.Если интерпретатор написан по-стандарту (и здравому смыслу),
&&
будут идти слева-направо. V8 / SpiderMonkey / Chakra работают именно такНе совсем понимаю за что вас минусуют. Если вы не против, я добавлю комментарии к вашему коду, что-бы читателям стало понятно.
Для начала, это абсолютно валидный код с точки зрения
C
.#define
директива — это по-сути замена во время компиляции найденого токена (или вызова) на его значени. В случае выше, любая найденнаяa
будет заменена на(__COUNTER__+1)
__COUNTER__
— это "магическое" макро значение, как и__FILE__
,__LINE__
, или__FUNCTION_
. И вC
/C++
эти значения опять же заменяются на этапе компиляции (см. выше). Сам же__COUNTER__
"магичен" из-за того, что при каждом новом вызове, он будет инкриментировать свое значение (от 0).В итоге выражение
(__COUNTER__+1)
станет(0+1)
, затем(1+1)
, затем(2+1)
.И весь код будет выглядеть так:
А дальше все еще круче, если кому интересно, компилятор просто схлопнет (оптимизирует) константные выражения, и на выходе останется:
Так-что не спешите кидаться на zawodskoj
А что, если злобный админ поставит прокси перед
/api/signin
и будет писать не захешированные пароли (а напомню, они именно так по сети гуляют) в файлик?И опять же, см. пункт с ресетом пароля, если он есть, то вы и так сможете получить письмо.
Могу ошибаться, но у Github синхронизация только между табами одного устройства, и скорее всего через localstorage / cookie в браузере.
А вот с подходом, описанном выше, так не получится. Нужен сервер в любом случае.
Но нужно еще продумать о безопасность этого подхода, т.к. хранить только email в клиентской сессии, вообще не безопасно, нужно тогда возвращать какой-нибудь секрет от запроса, сгенерированный бэком, а также хранить его в
sign_in_requests
таблице.С хранением на бэке, примерна такая-же история, нужно будет записывать guid сессии (cookie-based сессии) в таблицу
sign_in_requests
, и опять же сверять при рефреше сочетаниеemail
+secret
.Если я вас правильно понял, вы хотите, чтобы страница (с которой отправлен запрос) сама перезагрузилась, когда вы перейдете по ссылке из письма. Идея хорошая, но тут может появиться излишние затраты либо на Long polling, либо на полноценный Web socket (запросы по таймаута — зверство, поэтому я их не рассматриваю). Но этот вариант может решить проблему с телевизорами / IoT'ами.
Можно сделать менее красивый, но и менее затратный вариант: запоминать email на который выслали письма, а после ручного рефреша страницы (или перехода на другую страницу) проверять, перешел ли пользователь по ссылке из письма и окончательно авторизовать его. Т.е. получается такая двух этапная авторизация, на первом шаге мы просто записали email в переменную сессии (localstorage / cookie / backend session), а после подтверждения активировали эту сессию.
У нас есть HTTPS, а с Lets Encrypt вообще нет ни одной причины не использовать его.
К слову, а подтверждая email переходом из того же письма, вы более устойчивы к MITM?
А что вам в предложенной схеме мешает использовать свой почтовый сервер, если вы не доверяете гуглу?
К сожалению, я склонен больше верить в то, что у сайта с "котиками" будет все плохо, нежели у Yandex / Google / Mail.
А почему в предложено выше варианте они не могут сосуществовать? Вы можете позволить пользователю самостоятельно сделать выбор чем он хочет пользоваться: Oauth / Email + Pass / Email.
Если же вы боитесь, что почту могут своровать, и тогда пользователь потеряет доступ и к вашему сервису, так и с паролем (на вашей стороне) не многое поменяется (как минимум — ресет пароля на почту).
Использовать телефон (СМС) гораздо доже и менее безопасно, чем почту.
А если предположить, что номер телефона может утечь, то начнется спам. А вот спам на телефон в разы более мерзкий, чем на email. Если у email сервисов уже отлажены методы борьбы со спамом, то вот у телефонов все плачевно, будете получать звонки от "пирамид" с разных номеров.
Так она и не слезала с их плеч. Т.е. если у вас есть сброс пароля — у вас и не было никогда пароля.
Multi killТак и вижу, как я бегаю по комнате ищя кубики, чтобы авторизоваться на хабре :).