nedoPC.org

Electronics hobbyists community established in 2002
Atom Feed | View unanswered posts | View active topics It is currently 17 Apr 2024 18:55



Reply to topic  [ 20 posts ]  Go to page 1, 2  Next
JavaScript 
Author Message
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22523
Location: Silicon Valley
Reply with quote
Последние несколько лет язык JavaScript более-менее застандартизировали и им уже стало можно пользоваться без оглядки на особенности реализации тех или иных вещей в тех или иных браузерах. К тому же JavaScript можно назвать функциональным языком программирования - в нём можно функции передавать в другие функции и возвращать из других функций. Поэтому открываю топик для обсуждения всяких трюков и тонкостей, которые были бы полезны не только мне.

_________________
:dj: https://mastodon.social/@Shaos


15 Feb 2012 15:38
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22523
Location: Silicon Valley
Reply with quote
Post 
В функциональном программировании в JS есть одна несуразность, которая меня смущает (здесь и далее буду приводить выхлоп интерпретатора JS от мозиллы под названием Spidermonkey):
Code:
js> function a(b){return function(c){return b+c;};};
js> a(1)
function (c) {
    return b + c;
}
js> a(1)(2)
3

Как видим я определил функцию a, которая возвращает другую функцию - если выполнить a(1)(2), то оно вполне ожидаемо вернёт 3, а вот если выполнить a(1), то оно возвращает текст функции без изменений, однако я ожидал, что переменная b должна быть заменена на 1, т.е.:
Code:
function (c) {
    return 1 + c;
}

У кого есть какие мысли на этот счёт?

P.S. в Firefox и Konqueror оно ведёт себя точно также

_________________
:dj: https://mastodon.social/@Shaos


15 Feb 2012 15:41
Profile WWW
Devil

Joined: 26 May 2003 06:57
Posts: 859
Reply with quote
Post 
Shaos wrote:
У кого есть какие мысли на этот счёт?

Переменные в JS вычисляются только тогда, когда нужно их значение. А до тех пор они так и остаются переменной с определённым именем, т.к. в JS нет определённого деления на локальные и глобальные переменные (в том месте, где берётся значение переменной). Если нет локальной, то будет искаться глобальная.

В данном случае вызовы функций вложенные, т.е. к моменту вызова внутренней, внешняя имела в стеке локальных переменных (который общий для всех функций) значение b. Но вообще, это должно зависеть от реализации (уничтожать ли локальные переменные внешней функции при возврате тела внутренней функции как значения). С другой стороны, выражение a(1)(2) к моменту вычисления внутренней функции ещё не вычислено, а значит фактические параметры вызова a() ещё должны быть в стеке. Что мы и наблюдаем.

Получается, за уничножение локальных переменных в JS отвечает вызывающая программа (как в cdecl), а не вызванная (как в stdcall). :)

_________________
Страничка эмулятора наших компьютеров
http://bashkiria-2m.narod.ru/


15 Feb 2012 23:31
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22523
Location: Silicon Valley
Reply with quote
Post 
b2m wrote:
Shaos wrote:
У кого есть какие мысли на этот счёт?

Переменные в JS вычисляются только тогда, когда нужно их значение. А до тех пор они так и остаются переменной с определённым именем, т.к. в JS нет определённого деления на локальные и глобальные переменные (в том месте, где берётся значение переменной). Если нет локальной, то будет искаться глобальная.

В данном случае вызовы функций вложенные, т.е. к моменту вызова внутренней, внешняя имела в стеке локальных переменных (который общий для всех функций) значение b. Но вообще, это должно зависеть от реализации (уничтожать ли локальные переменные внешней функции при возврате тела внутренней функции как значения). С другой стороны, выражение a(1)(2) к моменту вычисления внутренней функции ещё не вычислено, а значит фактические параметры вызова a() ещё должны быть в стеке. Что мы и наблюдаем.

Получается, за уничножение локальных переменных в JS отвечает вызывающая программа (как в cdecl), а не вызванная (как в stdcall). :)


но тем не менее - вызов a(1) можно присвоить переменной и затем применить второй аргумент уже к ней:

Code:
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;
}

_________________
:dj: https://mastodon.social/@Shaos


16 Feb 2012 00:38
Profile WWW
Devil

Joined: 26 May 2003 06:57
Posts: 859
Reply with quote
Post 
В таком случае, фактические параметры (для необъявленых локальных переменных) должны сохраняться вместе с телом функции, просто JS их не выводит, когда переводит тело функции обратно в текстовый вид.

Можно ещё проверить, будут ли сохраняться значения глобальных переменных, которые используются в теле функции. Хотя, я полагаю, что они не будут сохраняться, на то они и глобальные.

А вот локальные переменные, объявленные во внешней функции, и используемые во внутренней, скорее всего тоже будут сохраняться вместе с телом, как и фактические параметры.

_________________
Страничка эмулятора наших компьютеров
http://bashkiria-2m.narod.ru/


16 Feb 2012 06:31
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22523
Location: Silicon Valley
Reply with quote
Post 
b2m wrote:
В таком случае, фактические параметры (для необъявленых локальных переменных) должны сохраняться вместе с телом функции, просто JS их не выводит, когда переводит тело функции обратно в текстовый вид.


И это делает отлаживание функционального программирования на JS практически невозможным...

_________________
:dj: https://mastodon.social/@Shaos


16 Feb 2012 07:52
Profile WWW
Doomed

Joined: 18 Feb 2007 11:40
Posts: 408
Reply with quote
Post 
Shaos wrote:
И это делает отлаживание функционального программирования на JS практически невозможным...

a(1) никогда не вернет то, что ты ожидал :)
И это правильно. Function statement requires a name!


16 Feb 2012 21:56
Profile
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22523
Location: Silicon Valley
Reply with quote
Post 
Different wrote:
Shaos wrote:
И это делает отлаживание функционального программирования на JS практически невозможным...

a(1) никогда не вернет то, что ты ожидал :)
И это правильно. Function statement requires a name!


Безымянные функции в JS вполне допустимы и широко применяются на практике

_________________
:dj: https://mastodon.social/@Shaos


16 Feb 2012 22:16
Profile WWW
Doomed

Joined: 18 Feb 2007 11:40
Posts: 408
Reply with quote
Post 
Shaos wrote:
Безымянные функции в JS вполне допустимы и широко применяются на практике

Да, если аргумент в наличии. А так получается - ни имени, ни аргумента.


19 Feb 2012 21:57
Profile
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22523
Location: Silicon Valley
Reply with quote
Post 
Different wrote:
Shaos wrote:
Безымянные функции в JS вполне допустимы и широко применяются на практике

Да, если аргумент в наличии. А так получается - ни имени, ни аргумента.


Ну и в чём проблема? Можно передать анонимную функцию из другой функции и применить к ней аргумент позже - всё работает как надо, просто при логировании печать неверная...

_________________
:dj: https://mastodon.social/@Shaos


20 Feb 2012 12:54
Profile WWW
Doomed

Joined: 18 Feb 2007 11:40
Posts: 408
Reply with quote
Post 
Shaos wrote:
Ну и в чём проблема? Можно передать анонимную функцию из другой функции и применить к ней аргумент позже - всё работает как надо, просто при логировании печать неверная...

Так нет никаких проблем, если правильно писать скрипты.
А в чем печать при логгировании неверная? Оно и в реальной ситуации через alert() выдаст тоже самое.


20 Feb 2012 22:04
Profile
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22523
Location: Silicon Valley
Reply with quote
Post 
Different wrote:
Shaos wrote:
Ну и в чём проблема? Можно передать анонимную функцию из другой функции и применить к ней аргумент позже - всё работает как надо, просто при логировании печать неверная...

Так нет никаких проблем, если правильно писать скрипты.
А в чем печать при логгировании неверная? Оно и в реальной ситуации через alert() выдаст тоже самое.


Какой алерт? См. внимательно - объясняю по шагам "на пальцах":

Объявляем функцию с одним аргументом: function a(b){return function(c){return b+c;};};
которая возвращает другую анонимную функцию, внутри которой использован этот один внешний аргумент

При вызове a(1)(2) оно корректно возвращает 3

А вот при вызове a(1) оно вместо
Code:
function (c) {
    return 1 + c;
}

возвращает
Code:
function (c) {
    return b + c;
}


То что это лишь ошибка печати я показал тем, что сохранил эту возвращённую функцию в переменной (тем самым дав имя этой анонимной функции):
var aa = a(1);
после чего вызов aa(2) вполне ожидаемо даёт 3, т.е. aa действительно имеет в себе function(c){return 1+c;}

т.е. я склоняюсь к объяснению, полученному от b2m:
b2m wrote:
фактические параметры (для необъявленых локальных переменных) должны сохраняться вместе с телом функции, просто JS их не выводит, когда переводит тело функции обратно в текстовый вид.

_________________
:dj: https://mastodon.social/@Shaos


20 Feb 2012 23:05
Profile WWW
Doomed

Joined: 18 Feb 2007 11:40
Posts: 408
Reply with quote
Post 
Shaos wrote:
То что это лишь ошибка печати я показал тем, что сохранил эту возвращённую функцию в переменной (тем самым дав имя этой анонимной функции)

Нет там никаких ошибок печати :) RTFM
Этой анонимной функции ты имя не давал, так как только присвоил объект переменной.
А так как параметр не передается в анонимную функцию, то и вызова функции не происходит, и return возвращает только тело функции, что вполне закономерно и ожидаемо.

"Для того чтобы научится правильно пользоваться функциями в JavaScript их нужно воспринимать как обычные данные": (c) http://xdan.ru/Funcional-JavaScript.html


26 Feb 2012 22:26
Profile
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22523
Location: Silicon Valley
Reply with quote
Post 
Different wrote:
Shaos wrote:
То что это лишь ошибка печати я показал тем, что сохранил эту возвращённую функцию в переменной (тем самым дав имя этой анонимной функции)

Нет там никаких ошибок печати :) RTFM
Этой анонимной функции ты имя не давал, так как только присвоил объект переменной.
А так как параметр не передается в анонимную функцию, то и вызова функции не происходит, и return возвращает только тело функции, что вполне закономерно и ожидаемо.


как это ожидаемо тело функции, если никакого b там уже нет и быть не может?
Code:
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;
}

и что-то я не улавливаю как безымянность функции соотносится со связанностью используемых внутри неё переменных..

_________________
:dj: https://mastodon.social/@Shaos


26 Feb 2012 23:55
Profile WWW
Admin
User avatar

Joined: 08 Jan 2003 23:22
Posts: 22523
Location: Silicon Valley
Reply with quote
Post 
Ещё более подробно для тех кто ещё не понял суть проблемы:
Code:
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;
}


Как видим при печати plus1,puls2.plus3 выдают одно и тоже, хотя вместо b в первом случае должно быть 1, во втором 2, в третьем 3, ну или хотя бы что-то типа такого меня тоже устроило бы:
Code:
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

_________________
:dj: https://mastodon.social/@Shaos


28 Feb 2012 17:33
Profile WWW
Display posts from previous:  Sort by  
Reply to topic   [ 20 posts ]  Go to page 1, 2  Next

Who is online

Users browsing this forum: No registered users and 18 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group
Designed by ST Software.