Pull to refresh

Comments 68

Когда человек наконец-то узнает все тайны Вселенной, он перестанет смеяться.
Это и не должно вызывать смех, это глубокая мысль, ну или просто мысль.
> он перестанет смеяться.
> не смешно

Улавливаете иронию?
UFO just landed and posted this here
так что же такое WAT? — не нашла нигде расшифровки ;-)
Доклад не звучал, как недоумение «как такое может быть?!». Автор доклада понимал каждое действие, которое он делал и понимал, что должно произойти. Суть доклада — показать, что эти моменты — это баг. А вы их объяснили, и сделали из них фичу.
Но, это не то поведение, которое ожидает увидеть программист в нормальном стандартном языке программирования. По этому, это все же баг.
Не ради холивара: сами гуру джаваскрипта понимают, что язык не очень выразителен и логичен, но альтернатив пока нету (CoffeeScript не считается).
Сорри. Не доглядел, что это перевод, а не ваша статья.
Не ради холивара, но что значит «не очень выразителен и логичен»?
> эти моменты — это баг
> это не то поведение, которое ожидает увидеть программист в нормальном стандартном языке программирования

А какого поведения ожидали вы? Что язык с мягкой типизацией и перебитым оператором "+" (с приведением к строке, как типу по умолчанию) выкинет исключение? Свалится с ошибкой? Остановит компиляцию (_ирония_)?

Серьёзно, лично вы какого поведения бы ожидали?
Лично я ожидал бы как минимум того, что если typeof(a) == typeof(b) == Array, то a + b == a.append(b). И вообще, на мой взгляд, невозможность оверлоадить операторы в JavaScript — полнейшее недоразумение.
Какую-то глупость сказал. Я имел в виду a + b == [a[0], a[1], ..., a[a.length], b[0], b[1], ..., b[b.length]]
Было бы правильней, по-моему,
a + b == [a[0], a[1], ..., a[a.length-1], b[0], b[1], ..., b[b.length-1]]

Ааааргх! Простите, я сегодня невнимательный :(
UFO just landed and posted this here
> И вообще, на мой взгляд, невозможность оверлоадить операторы в JavaScript — полнейшее недоразумение.

А на мой взгляд нормально. Не хватало ещё чтобы те кучи кода, которые Вы подключаете к проекту, могли перегружать такие стандартные операторы. Хватает изменения глобальных объектов и прототипов. «Счастливой отладки» будет в лучшем виде.
UFO just landed and posted this here
Суперссылка! Но ниндзюцу — это не путь самурая.
Мои ожидания:
[] + [] = []
[] + {} = undefined (или какой-то еще объект, который укажет, что произошла нестандартная операци; или поднять исключение)
{} + [] = [] + {}
a + b = b + a (!!!!!!!!!)
{} + {} = {}
Да, согласен {} + [] != [] + {} — совсем не очевидно
UFO just landed and posted this here
конкатенация чего? Есть конкатенация строк: строка + строка, а тут конкатенация `яблоко` + `волнистый попугайчик`. Что ты ожидаешь получить в результате? `яблоко` + `волнистый попугайчик` =?
(a + b) даже в C не всегда равно (b + a)
a + b = b + a (!!!!!!!!!)

странные ожидания.

a = 'foo';
b = 'bar';

a+b == 'foobar';
b+a == 'barfoo';


И с какого хрена они должны быть равными?
> {} + []
0
> [] + {}
"[object Object]"


Да, все очевидно и ожидаемо, не правда ли? С какого хрена яблоко + шум дождя = демократия? Как можно проводить операции над разными типами?
Где еще кроме строк должна не работать коммутативность?
UFO just landed and posted this here
Не очень понял смысл поста (вижу, что перевод).
Не думаю, что кто-то из программистов сомневался, что поведение jsc-интерпретатора, продемонстрированное на видео, противоречит спецификации языка. Естественно, результат логичен в том плане, что его можно без сложностей объяснить, последовательно рассмотрев каждую операцию.
Дело в другом, в человеческой логике.

Сложение массивов через оператор (+) — занятие сомнительное, но если язык это позволяет, то логично, что программист ожидает получить на выходе массив, элементами которого будут суммы элементов массивов (в соот. последовательности). Ну или null, если так делать нельзя. Или пустой массив, на худой конец.
Пустая строка в результате — это нелогично ни разу. Хотя и по спецификации.

И так далее.

Понятно, что специалиста, который уже привык пользоваться своим инструментом, привык к подобному «нормальному поведению», такими фокусами не удивить. Более того, он может использовать эти фокусы в реальном проекте, чтобы делать что-то быстрее и проще. Никто не спорит. Но продуманности и логичности языку это не прибавляет.
UFO just landed and posted this here
«Человеческую логику», в той форме, в которой Вы ее описали, принято называть «интуицией». Программист должен «не надеяться и верить», а «знать». И из этого знания получать логически стройную программу.
Не согласен с Вами — язык должен ориентироваться на обычную логику человека, и дела не втом, что должен программист, а что не должен.
Программист — прежде всего — человек.
Можно и define true false сделать — и описать это в стандарте языка — это не протеворечит ничему.
НО! Это противоречит ожидаемому поведению — отсюда — буду возникать ошибки.

Хороший язык с моей точки зрения:
1) ведет ожидаемо с точки зрения человека, ибо написан он прежде всего для него
2) ограничивает возможность совершить ошибку

Отрекшись от знаний JS подумайте просто чисто из ощущений — если вы складываете два массива что вы должны получить? cтроку?

Язык должен помогать человеку, ведь он для него и написан.
Мне очень нравится JS и он все больше стремится к идеальному языку, и надеюсь эти грабли в конце концов уберут как было с with
Даже естественные языки, несмотря на свою многовековую историю, не очень-то логичны с точки зрения человека. Попробуйте учить китайский или чеченский. Вам родной язык кажется логичным потому, что Вы его зубрили с пеленок. К примеру, почему «стол» — это он, а «парта» — это она? Вам это кажется логичным. А вот очень многим людям чуждо даже само понятие грамматического рода.
Вы можете возразить, что искусственные языки изобретались целенаправленно и лишены логических изъянов естественных языков. И так должно быть и с языками программирования. Но почему тогда почти никто на искуственных языках не говорит? Да потому, что они «кажутся» людям не логичными.

Пример из жизни. Если я складываю два сырых яйца, что я должен получить? Ожидается, что два яйца. А если с силой? Да друг об друга?

Кстати, в опытных руках грабли являются не инструментом самоубийства, а полезным сельхозорудием: с помощью with можно было эмулировать let.
Ну во-первых складывая два яйца независмо от способа вы получите всетеже два яйца, просто складывая их с силой вы получите два БИТЫХ яйца ) Сущность у Вас не поменялась, поменялось состояние.

Во вторых, логика в программистких языках математическая и никак уж не ассоциируется с обычными языками. В математике говорится — если Вы складываете два слона на выходе вы должны получить ту же сущность. И это одинаково что для математика из Южной Гвинеи, что для Эскимоса, не находите?

По поводу with — его убрали из-за неочивидности поведения, да им можно было кое-что и полезное делать, но ИМХО — правильно что убрали. Хотите скоп — вводите скоп, а не странную функцию с неоднозначным поведением. Ошибок можно было наплодить с ним, даже зная все его особенности.
Вы не находите, что я говорю именно об этом? Если «логика в программистких языках математическая», то нечего к ней подходить с житейской точки зрения. Если у Вас изначально неверная посылка «во всех языках массив плюс массив дает массив», то нечего удивляться, что и заключение «в JavaScript массив плюс массив должен давать массив» получается неверное.
Математическая логика про массивы ничего не знает, она лишь говорит что при сложении сущностей результатом будет такая же сущность. Это вполне интуитивно, не так ли?

Тут не причем житейская логика.

И да, язык ИМЕЕТ право на то, что массив плюс массив дает строку, но это поведение отличается от ожидаемого.

Он ИМЕЕТ на это право, но если бы он делал это ОЖИДАЕМО — количество бы ошибок УМЕНЬШИЛОСЬ — вот что я имел ввиду.
UFO just landed and posted this here
Вы должны знать, что отвечать надо с помощью ссылки «ответить» под комментарием. А я вот проинтуичил, что ваш комментарий — это ответ на мой, хотя тред другой. Интуиция — это иногда даже удобно, правда?:)

Я ещё раз повторюсь (видимо, не достаточно полно донес эту мысль в своем первом комментарии), что специалист обязан знать инструменты, которыми пользуется. Это правило применимо к любому специалисту, не только к программисту. Другое дело, что специалист работает с определенными абстракциями, и ожидает, что конкретные реализации этих абстракций на местах не будут вносить изменения в сами абстракции. На то они абстр… ну вы поняли. Я думаю, инженер очень удивится, если получит в руки штангенциркули, которые можно «складывать», и получая отбойные молотки. Это неправильные штангенциркули, их проектировщики не продумали архитектуру, и теперь эксплуататорам приходится переучиваться и быть настороже.

Курс «алгоритмы и структуры данных» независим от языка, на котором будут написаны примеры, потому что абстракция массива проста и понятна, и едина (должна быть) для всех инструментом, использующих эту абстракцию. Если математик складывает массивы, он удивится строке в результате, это WAT. Не больше и не меньше. А спецы пусть мучаются или радуются — их дело. :) Если уж говорить о JS, то мне нравится, что все — строка, типизации нет и т.д., с этим проще работать (до определенного уровня сложности систем, конечно), но над докладом я посмеялся.
После этого поста у меня сложилось впечатление о полном отсутствии юмора у JS программистов. Всякие вещи на подобии []+[]='' и {}+[] != []+{} ведь ни разу не логичны с точки зрения математики и могут свернуть мозг набок. А для тех, у кого wat-пост вызвал бурю негодования — Ну пошутили и будет вам, чего так напрягаться то?
Рискую быть сильно заминусованным, но все же спрошу:
В топике упомянут eval для парса JSON…
А какой метод парса JSON, полученного через AJAX, является расово верным, и почему?
Точнее, что плохого в eval?
Нет, eval конечно небезопасен, но если данные приходят от моего же сервера, в котором я абсолютно уверен, в чем может быть проблема?
Ладно бы в JS существовал кроссбраузерный вариант нативного парса JSON, так нет же, для некоторых браузеров нужны костыли. Не совсем понимаю, в чем целесообразность отказа от eval?
Но это кастомный парсер, а не нативная функция. В чем смысл использования ее вместо нативного eval?
1. Это нативная функция, начиная с 5-ой версии стандарта.
2. Смысл в безопасности.
Ну eval плох только тем что не безопасен.
JSON parser жертвуя скоростью, дает уверенность в безопасности — т.е. он только преобразует валидный json в объект, и не может выполнить произвольный код, в отличает от eval.
Да, я знаю об этом. Но как всегда, есть особенный браузер… :D Который не в курсе.

А все же, как может проявиться «небезопасность» eval'а при условии парса таким образом ответа от своего же сервера?
Почему вы уверены, что получаете ответ именно от своего сервера?
Почему вы уверены, что ответ от вашего сервера не может содержать атакующего кода?
Код исполняется на клиенте и подвержен разным видам атаки.
Я полагал, что кроссдоменные запросы по умолчанию не работают.
А если есть возможность подменить произвольный ответ от сервера, то можно сразу исходную страницу и подменить, зачем мучиться с подменой AJAX?
Аналогично с вариантом атакующего кода от сервера.
Впрочем, я думаю, что продолжать дискуссию смысла нет. Простое любопытство тут карается :(
Это нервные понабежали. )

По поводу атак недавно на хабре проскакивало несколько статей про XSS. Очень показательно. :)
Видимо да :) Даже кое-куда нагадить успели )
Я ж для самообразования спрашиваю, разобраться хочу. Для себя. Гуру JS себя не считаю, и eval не хвалю. Но понять хочу, а не слепо принять на веру «eval плохо».

Вообще да, есть в этом резон. Использование eval потенциально дает новые XSS. Однако, если формирование JSON на сервере автоматизировано (json_encode, например), то все спецсимволы будут экранированы, поэтому я не понимаю, где тут может быть проблема.
За исключением варианта скомпрометированного сервера или канала общения с сервером, но в этом случае, как я писал выше, разницы нет — JSON это будет или исходная страница.
Если не делать ошибок, все будет хорошо, угу. Но это редко случается с девелоперами. :)
Используя JSON.parse(), можно сделать свое приложение не менее безопасным, чем с eval(). Как правило, более безопасным. А цена — небольшая.
Да, пожалуй вы правы. парс ответа сервера — не то место, где следует экономить. Не настолько часто это происходит.
Даже если разница в безопасности минимальна, оно того стоит.

Спасибо за ответы :)
Пост следовало бы назвать «Оправдания интерпретатора».

Как говорил Джоэл, когда вы видите i=a+b, вы можете рассчитывать только на себя, парни )
Конечно, динамическая типизация способна привести к неочевидным результатам. Но, с другой стороны, более-менее опытный человек знает тонкости языка с которым он работает, а неопытный довольно быстро их поймет. Если захочет.
Ну и именования типа sI = sA + sB жизнь немного облегчают.
А я рубист, но ролик про WAT посмотрел со смехом и радостью. И мне ни разу не захотелось бежать строчить посты о том, что Руби тут не виноват и как–то оправдывать его в глазах общественности. Видео — просто юмор, к которому нужно относиться как к юмору.

Вот еще один WAT из Руби, который есть даже в самой последней версии:

1.9.3p0 :001 > a = []
=> []
1.9.3p0 :002 > a[0] = a
=> [[...]]
1.9.3p0 :003 > a
=> [[...]]
1.9.3p0 :004 > a[0]
=> [[...]]


И ничего, живем же как–то.
А что в этом примере не логично?
Как минимум многоточие и факт того, что так можно делать. Вон в Питоне в примере ниже подобное, но лишь отчасти.
Python

>>> a = [1,2]
>>> a
[1, 2]
>>> a[0] = a
>>> a
[[...], 2]
>>> a[1] = a
>>> a
[[...], [...]]
>>> a[0]
[[...], [...]]
>>> a[0][1]
[[...], [...]]
Ну и… что не оффтоп:
>>> a + a
[[[...], [...]], [[...], [...]], [[...], [...]], [[...], [...]]]
UFO just landed and posted this here
UFO just landed and posted this here
boolean, null, undefined преобразуются к числам (true = 1, false = 0, null = 0, undefined = NaN)
объекты, массивы, функции преобразуются к строкам.

А объект Date с унарными плюсом возвращает число (через valueOf), но при сложении с числами — всё-таки строку.

Вот эта таблица неплохо всё иллюстрирует:
docstore.mik.ua/orelly/webprog/jscript/ch11_01.htm#jscript4-CHP-11-SECT-1
Ребята, подскажите, пожалуйста. Вот {} + {} будет равно NaN.
Но вот при таком коде:
var a = {};
var b = {};
выражение a + b будет равно [object Object][object Object]
Почему так?
если фигурная скобка находится в начале выражения, она будет интерпретирована как начало блока кода

Очевидно, в случае с переменными такая порблема не возникает.
Сравните ({}) + {} и {} + {}.
Большое спасибо. Надо было внимательнее читать, конечно. Но гениально вообще!
Sign up to leave a comment.

Articles