Author |
Message |
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22827 Location: Silicon Valley
|
Последние несколько лет язык JavaScript более-менее застандартизировали и им уже стало можно пользоваться без оглядки на особенности реализации тех или иных вещей в тех или иных браузерах. К тому же JavaScript можно назвать функциональным языком программирования - в нём можно функции передавать в другие функции и возвращать из других функций. Поэтому открываю топик для обсуждения всяких трюков и тонкостей, которые были бы полезны не только мне.
|
15 Feb 2012 15:38 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22827 Location: Silicon Valley
|
В функциональном программировании в JS есть одна несуразность, которая меня смущает (здесь и далее буду приводить выхлоп интерпретатора JS от мозиллы под названием Spidermonkey):
Как видим я определил функцию a, которая возвращает другую функцию - если выполнить a(1)(2), то оно вполне ожидаемо вернёт 3, а вот если выполнить a(1), то оно возвращает текст функции без изменений, однако я ожидал, что переменная b должна быть заменена на 1, т.е.:
У кого есть какие мысли на этот счёт?
P.S. в Firefox и Konqueror оно ведёт себя точно также
|
15 Feb 2012 15:41 |
|
|
b2m
Devil
Joined: 26 May 2003 06:57 Posts: 873
|
Переменные в JS вычисляются только тогда, когда нужно их значение. А до тех пор они так и остаются переменной с определённым именем, т.к. в JS нет определённого деления на локальные и глобальные переменные (в том месте, где берётся значение переменной). Если нет локальной, то будет искаться глобальная.
В данном случае вызовы функций вложенные, т.е. к моменту вызова внутренней, внешняя имела в стеке локальных переменных (который общий для всех функций) значение b. Но вообще, это должно зависеть от реализации (уничтожать ли локальные переменные внешней функции при возврате тела внутренней функции как значения). С другой стороны, выражение a(1)(2) к моменту вычисления внутренней функции ещё не вычислено, а значит фактические параметры вызова a() ещё должны быть в стеке. Что мы и наблюдаем.
Получается, за уничножение локальных переменных в JS отвечает вызывающая программа (как в cdecl), а не вызванная (как в stdcall).
_________________Страничка эмулятора наших компьютеров
http://bashkiria-2m.narod.ru/
|
15 Feb 2012 23:31 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22827 Location: Silicon Valley
|
| | | | b2m wrote: Переменные в JS вычисляются только тогда, когда нужно их значение. А до тех пор они так и остаются переменной с определённым именем, т.к. в JS нет определённого деления на локальные и глобальные переменные (в том месте, где берётся значение переменной). Если нет локальной, то будет искаться глобальная. В данном случае вызовы функций вложенные, т.е. к моменту вызова внутренней, внешняя имела в стеке локальных переменных (который общий для всех функций) значение b. Но вообще, это должно зависеть от реализации (уничтожать ли локальные переменные внешней функции при возврате тела внутренней функции как значения). С другой стороны, выражение a(1)(2) к моменту вычисления внутренней функции ещё не вычислено, а значит фактические параметры вызова a() ещё должны быть в стеке. Что мы и наблюдаем. Получается, за уничножение локальных переменных в JS отвечает вызывающая программа (как в cdecl), а не вызванная (как в stdcall). | | | | |
но тем не менее - вызов a(1) можно присвоить переменной и затем применить второй аргумент уже к ней:
|
16 Feb 2012 00:38 |
|
|
b2m
Devil
Joined: 26 May 2003 06:57 Posts: 873
|
В таком случае, фактические параметры (для необъявленых локальных переменных) должны сохраняться вместе с телом функции, просто JS их не выводит, когда переводит тело функции обратно в текстовый вид.
Можно ещё проверить, будут ли сохраняться значения глобальных переменных, которые используются в теле функции. Хотя, я полагаю, что они не будут сохраняться, на то они и глобальные.
А вот локальные переменные, объявленные во внешней функции, и используемые во внутренней, скорее всего тоже будут сохраняться вместе с телом, как и фактические параметры.
_________________Страничка эмулятора наших компьютеров
http://bashkiria-2m.narod.ru/
|
16 Feb 2012 06:31 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22827 Location: Silicon Valley
|
И это делает отлаживание функционального программирования на JS практически невозможным...
|
16 Feb 2012 07:52 |
|
|
Different
Doomed
Joined: 18 Feb 2007 11:40 Posts: 408
|
a(1) никогда не вернет то, что ты ожидал
И это правильно. Function statement requires a name!
|
16 Feb 2012 21:56 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22827 Location: Silicon Valley
|
Безымянные функции в JS вполне допустимы и широко применяются на практике
|
16 Feb 2012 22:16 |
|
|
Different
Doomed
Joined: 18 Feb 2007 11:40 Posts: 408
|
Да, если аргумент в наличии. А так получается - ни имени, ни аргумента.
|
19 Feb 2012 21:57 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22827 Location: Silicon Valley
|
Ну и в чём проблема? Можно передать анонимную функцию из другой функции и применить к ней аргумент позже - всё работает как надо, просто при логировании печать неверная...
|
20 Feb 2012 12:54 |
|
|
Different
Doomed
Joined: 18 Feb 2007 11:40 Posts: 408
|
Так нет никаких проблем, если правильно писать скрипты.
А в чем печать при логгировании неверная? Оно и в реальной ситуации через alert() выдаст тоже самое.
|
20 Feb 2012 22:04 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22827 Location: Silicon Valley
|
Какой алерт? См. внимательно - объясняю по шагам "на пальцах": Объявляем функцию с одним аргументом: function a(b){return function(c){return b+c;};};которая возвращает другую анонимную функцию, внутри которой использован этот один внешний аргумент При вызове a(1)(2) оно корректно возвращает 3 А вот при вызове a(1) оно вместо возвращает То что это лишь ошибка печати я показал тем, что сохранил эту возвращённую функцию в переменной (тем самым дав имя этой анонимной функции): var aa = a(1);после чего вызов aa(2) вполне ожидаемо даёт 3, т.е. aa действительно имеет в себе function(c){return 1+c;}т.е. я склоняюсь к объяснению, полученному от b2m:
|
20 Feb 2012 23:05 |
|
|
Different
Doomed
Joined: 18 Feb 2007 11:40 Posts: 408
|
Нет там никаких ошибок печати RTFM
Этой анонимной функции ты имя не давал, так как только присвоил объект переменной.
А так как параметр не передается в анонимную функцию, то и вызова функции не происходит, и return возвращает только тело функции, что вполне закономерно и ожидаемо.
" Для того чтобы научится правильно пользоваться функциями в JavaScript их нужно воспринимать как обычные данные": (c) http://xdan.ru/Funcional-JavaScript.html
|
26 Feb 2012 22:26 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22827 Location: Silicon Valley
|
| | | | Different wrote: Нет там никаких ошибок печати RTFM Этой анонимной функции ты имя не давал, так как только присвоил объект переменной. А так как параметр не передается в анонимную функцию, то и вызова функции не происходит, и return возвращает только тело функции, что вполне закономерно и ожидаемо. | | | | |
как это ожидаемо тело функции, если никакого b там уже нет и быть не может?
и что-то я не улавливаю как безымянность функции соотносится со связанностью используемых внутри неё переменных..
|
26 Feb 2012 23:55 |
|
|
Shaos
Admin
Joined: 08 Jan 2003 23:22 Posts: 22827 Location: Silicon Valley
|
Ещё более подробно для тех кто ещё не понял суть проблемы:
Как видим при печати plus1,puls2.plus3 выдают одно и тоже, хотя вместо b в первом случае должно быть 1, во втором 2, в третьем 3, ну или хотя бы что-то типа такого меня тоже устроило бы:
|
28 Feb 2012 17:33 |
|
|