JavaScript
Moderator: Shaos
-
- Admin
- Posts: 24083
- Joined: 08 Jan 2003 23:22
- Location: Silicon Valley
JavaScript
Последние несколько лет язык JavaScript более-менее застандартизировали и им уже стало можно пользоваться без оглядки на особенности реализации тех или иных вещей в тех или иных браузерах. К тому же JavaScript можно назвать функциональным языком программирования - в нём можно функции передавать в другие функции и возвращать из других функций. Поэтому открываю топик для обсуждения всяких трюков и тонкостей, которые были бы полезны не только мне.
Я тут за главного - если что шлите мыло на me собака shaos точка net
-
- Admin
- Posts: 24083
- Joined: 08 Jan 2003 23:22
- Location: Silicon Valley
В функциональном программировании в JS есть одна несуразность, которая меня смущает (здесь и далее буду приводить выхлоп интерпретатора JS от мозиллы под названием Spidermonkey):
Как видим я определил функцию a, которая возвращает другую функцию - если выполнить a(1)(2), то оно вполне ожидаемо вернёт 3, а вот если выполнить a(1), то оно возвращает текст функции без изменений, однако я ожидал, что переменная b должна быть заменена на 1, т.е.:
У кого есть какие мысли на этот счёт?
P.S. в Firefox и Konqueror оно ведёт себя точно также
Code: Select all
js> function a(b){return function(c){return b+c;};};
js> a(1)
function (c) {
return b + c;
}
js> a(1)(2)
3
Code: Select all
function (c) {
return 1 + c;
}
P.S. в Firefox и Konqueror оно ведёт себя точно также
Я тут за главного - если что шлите мыло на me собака shaos точка net
-
- Devil
- Posts: 907
- Joined: 26 May 2003 06:57
Переменные в JS вычисляются только тогда, когда нужно их значение. А до тех пор они так и остаются переменной с определённым именем, т.к. в JS нет определённого деления на локальные и глобальные переменные (в том месте, где берётся значение переменной). Если нет локальной, то будет искаться глобальная.Shaos wrote:У кого есть какие мысли на этот счёт?
В данном случае вызовы функций вложенные, т.е. к моменту вызова внутренней, внешняя имела в стеке локальных переменных (который общий для всех функций) значение b. Но вообще, это должно зависеть от реализации (уничтожать ли локальные переменные внешней функции при возврате тела внутренней функции как значения). С другой стороны, выражение a(1)(2) к моменту вычисления внутренней функции ещё не вычислено, а значит фактические параметры вызова a() ещё должны быть в стеке. Что мы и наблюдаем.
Получается, за уничножение локальных переменных в JS отвечает вызывающая программа (как в cdecl), а не вызванная (как в stdcall).

Страничка эмулятора наших компьютеров
http://bashkiria-2m.narod.ru/
http://bashkiria-2m.narod.ru/
-
- Admin
- Posts: 24083
- Joined: 08 Jan 2003 23:22
- Location: Silicon Valley
но тем не менее - вызов a(1) можно присвоить переменной и затем применить второй аргумент уже к ней:b2m wrote:Переменные в JS вычисляются только тогда, когда нужно их значение. А до тех пор они так и остаются переменной с определённым именем, т.к. в JS нет определённого деления на локальные и глобальные переменные (в том месте, где берётся значение переменной). Если нет локальной, то будет искаться глобальная.Shaos wrote:У кого есть какие мысли на этот счёт?
В данном случае вызовы функций вложенные, т.е. к моменту вызова внутренней, внешняя имела в стеке локальных переменных (который общий для всех функций) значение b. Но вообще, это должно зависеть от реализации (уничтожать ли локальные переменные внешней функции при возврате тела внутренней функции как значения). С другой стороны, выражение a(1)(2) к моменту вычисления внутренней функции ещё не вычислено, а значит фактические параметры вызова a() ещё должны быть в стеке. Что мы и наблюдаем.
Получается, за уничножение локальных переменных в JS отвечает вызывающая программа (как в cdecl), а не вызванная (как в stdcall).
Code: Select all
js> function a(b){return function(c){return b+c;};};
js> var aa = a(1);
js> aa(2)
3
js> aa
function (c) {
return b + c;
}
Я тут за главного - если что шлите мыло на me собака shaos точка net
-
- Devil
- Posts: 907
- Joined: 26 May 2003 06:57
В таком случае, фактические параметры (для необъявленых локальных переменных) должны сохраняться вместе с телом функции, просто JS их не выводит, когда переводит тело функции обратно в текстовый вид.
Можно ещё проверить, будут ли сохраняться значения глобальных переменных, которые используются в теле функции. Хотя, я полагаю, что они не будут сохраняться, на то они и глобальные.
А вот локальные переменные, объявленные во внешней функции, и используемые во внутренней, скорее всего тоже будут сохраняться вместе с телом, как и фактические параметры.
Можно ещё проверить, будут ли сохраняться значения глобальных переменных, которые используются в теле функции. Хотя, я полагаю, что они не будут сохраняться, на то они и глобальные.
А вот локальные переменные, объявленные во внешней функции, и используемые во внутренней, скорее всего тоже будут сохраняться вместе с телом, как и фактические параметры.
Страничка эмулятора наших компьютеров
http://bashkiria-2m.narod.ru/
http://bashkiria-2m.narod.ru/
-
- Admin
- Posts: 24083
- Joined: 08 Jan 2003 23:22
- Location: Silicon Valley
И это делает отлаживание функционального программирования на JS практически невозможным...b2m wrote:В таком случае, фактические параметры (для необъявленых локальных переменных) должны сохраняться вместе с телом функции, просто JS их не выводит, когда переводит тело функции обратно в текстовый вид.
Я тут за главного - если что шлите мыло на me собака shaos точка net
-
- Doomed
- Posts: 408
- Joined: 18 Feb 2007 11:40
-
- Admin
- Posts: 24083
- Joined: 08 Jan 2003 23:22
- Location: Silicon Valley
Безымянные функции в JS вполне допустимы и широко применяются на практикеDifferent wrote:a(1) никогда не вернет то, что ты ожидалShaos wrote:И это делает отлаживание функционального программирования на JS практически невозможным...
И это правильно. Function statement requires a name!
Я тут за главного - если что шлите мыло на me собака shaos точка net
-
- Doomed
- Posts: 408
- Joined: 18 Feb 2007 11:40
-
- Admin
- Posts: 24083
- Joined: 08 Jan 2003 23:22
- Location: Silicon Valley
Ну и в чём проблема? Можно передать анонимную функцию из другой функции и применить к ней аргумент позже - всё работает как надо, просто при логировании печать неверная...Different wrote:Да, если аргумент в наличии. А так получается - ни имени, ни аргумента.Shaos wrote:Безымянные функции в JS вполне допустимы и широко применяются на практике
Я тут за главного - если что шлите мыло на me собака shaos точка net
-
- Doomed
- Posts: 408
- Joined: 18 Feb 2007 11:40
Так нет никаких проблем, если правильно писать скрипты.Shaos wrote: Ну и в чём проблема? Можно передать анонимную функцию из другой функции и применить к ней аргумент позже - всё работает как надо, просто при логировании печать неверная...
А в чем печать при логгировании неверная? Оно и в реальной ситуации через alert() выдаст тоже самое.
-
- Admin
- Posts: 24083
- Joined: 08 Jan 2003 23:22
- Location: Silicon Valley
Какой алерт? См. внимательно - объясняю по шагам "на пальцах":Different wrote:Так нет никаких проблем, если правильно писать скрипты.Shaos wrote: Ну и в чём проблема? Можно передать анонимную функцию из другой функции и применить к ней аргумент позже - всё работает как надо, просто при логировании печать неверная...
А в чем печать при логгировании неверная? Оно и в реальной ситуации через alert() выдаст тоже самое.
Объявляем функцию с одним аргументом: function a(b){return function(c){return b+c;};};
которая возвращает другую анонимную функцию, внутри которой использован этот один внешний аргумент
При вызове a(1)(2) оно корректно возвращает 3
А вот при вызове a(1) оно вместо
Code: Select all
function (c) {
return 1 + c;
}
Code: Select all
function (c) {
return b + c;
}
var aa = a(1);
после чего вызов aa(2) вполне ожидаемо даёт 3, т.е. aa действительно имеет в себе function(c){return 1+c;}
т.е. я склоняюсь к объяснению, полученному от b2m:
b2m wrote:фактические параметры (для необъявленых локальных переменных) должны сохраняться вместе с телом функции, просто JS их не выводит, когда переводит тело функции обратно в текстовый вид.
Я тут за главного - если что шлите мыло на me собака shaos точка net
-
- Doomed
- Posts: 408
- Joined: 18 Feb 2007 11:40
Нет там никаких ошибок печатиShaos wrote: То что это лишь ошибка печати я показал тем, что сохранил эту возвращённую функцию в переменной (тем самым дав имя этой анонимной функции)

Этой анонимной функции ты имя не давал, так как только присвоил объект переменной.
А так как параметр не передается в анонимную функцию, то и вызова функции не происходит, и return возвращает только тело функции, что вполне закономерно и ожидаемо.
"Для того чтобы научится правильно пользоваться функциями в JavaScript их нужно воспринимать как обычные данные": (c) http://xdan.ru/Funcional-JavaScript.html
-
- Admin
- Posts: 24083
- Joined: 08 Jan 2003 23:22
- Location: Silicon Valley
как это ожидаемо тело функции, если никакого b там уже нет и быть не может?Different wrote:Нет там никаких ошибок печатиShaos wrote: То что это лишь ошибка печати я показал тем, что сохранил эту возвращённую функцию в переменной (тем самым дав имя этой анонимной функции)RTFM
Этой анонимной функции ты имя не давал, так как только присвоил объект переменной.
А так как параметр не передается в анонимную функцию, то и вызова функции не происходит, и return возвращает только тело функции, что вполне закономерно и ожидаемо.
Code: Select all
js> function a(b){return function(c){return b+c;};};
js> var aa = a(1);
js> aa(2)
3
js> aa
function (c) {
return b + c;
}
Я тут за главного - если что шлите мыло на me собака shaos точка net
-
- Admin
- Posts: 24083
- Joined: 08 Jan 2003 23:22
- Location: Silicon Valley
Ещё более подробно для тех кто ещё не понял суть проблемы:
Как видим при печати plus1,puls2.plus3 выдают одно и тоже, хотя вместо b в первом случае должно быть 1, во втором 2, в третьем 3, ну или хотя бы что-то типа такого меня тоже устроило бы:
Code: Select all
js> function a(b){return function(c){return b+c;};};
js> var plus1=a(1);
js> var plus2=a(2);
js> var plus3=a(3);
js> plus1(100)
101
js> plus2(100)
102
js> plus3(100)
103
js> plus1
function (c) {
return b + c;
}
js> plus2
function (c) {
return b + c;
}
js> plus3
function (c) {
return b + c;
}
Code: Select all
js> plus1
function (c) {
return b + c;
}
where b=1
js> plus2
function (c) {
return b + c;
}
where b=2
js> plus3
function (c) {
return b + c;
}
where b=3
Я тут за главного - если что шлите мыло на me собака shaos точка net