Pull to refresh
6
0
Алексей Волков@AlekseiVolkov

Старший разработчик интерфейсов в Люксофте

Send message

Отличный вопрос!

А можно не выдумывать сложности там где их нет

100% можно. Это лишь пример, именно в нём конечно не нужен редакс. Но и ваш пример как раз про автоматное программирование - переход от событийной логики в конечному автомату.
Редакс это просто реализация такого подхода в реакте. Чтобы не всё приложение перерисовывалось и прочие плюшки.

Что вам это дало?

А если Vue? Angular? Solid?

Это пример будущих мыслей бизнеса и техлидов.

Значит ли это, что при обновлении части состояния, например с PLAYING на PAUSED, пользователь это не увидет?

В реакте можем использовать редакс* в корне и он не будет вызывать перерисовок всего приложения.

* – redux + react-redux

Чтобы что? Для чего? Да, мы знаем, что редакс подает как мегафишку то, что вообще говоря почти никогда не требуется, а если требуется, то очень легко реализуется и без него?

Чисто для отладки. Чтобы не console.log писать (даже через debugger), а видеть как менялось состояние. А как без редакса смотреть и менять состояние вашего примера handleEvent?

Отлично, что нашли что-то общее! Да, я увидел что от версии к версии спека может отличаться прилично. Смотрел на первую версию ради человеческих объяснений, потом только текущую версию смотрел.

"скопировать в место использования" - всё ещё не понимаю где абстракция, где спека. Я хотел разобраться, что за замыкание в JS, не узнать очередную интерпретацию спеки, а понять буквально её. Увидел только "поиск" переменной, без других вариантов нахождения переменных. Если вы про V8, то да, я не знаю как там JS работает.

Спасибо за разъяснение. Понял, что для вас "замыкание" - это возможность языка, как и каррирование.

Но я всё равно не понимаю его реализацию в рамках спеки или V8. Каррирование можно разложить на части и их поведение найти в спеке. Вашу логику про "замыкание" отличное от "поиска" я не могу разложить. Не понимаю каким ещё образом можно найти переменную как не через "поиск".

Почитал определение замыкания в википедии. Оно очень размыто. Меня же интересовала реализация в JavaScript.

Разницу Environment и Environment Record я тоже не нашёл. 9.1 Environment Records описывает поведение так, будто Environment Record - это список переменных (bindings). Хоть, как я и говорил, это звучит тупо.

Спасибо, понял вашу логику.

Но я не увидел в спеке механизма "замыкание" из вашей логики. Я увидел лишь "поиск" - это описание взял из 9.1.2.1 GetIdentifierReference ( env, name, strict ).

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

Про Environment Record как список записей - согласен, звучит тупо... но как есть. Просто хотел в рамках спеки что-то понять и объяснить. А то мгновенно путаюсь.

Спасибо за предложения.

В итоге мы с вами единого мнения? Реализация под капотом может быть разной, но мы называем одни вещи немного разными словами.

Я говорю, что "контекст" = "окружение" = Environment Record. И "замыкание" - это механизм нахождения переменной в цепочке Environment Record.

Другого "замыкания" не существует. Согласны?

Спасибо за пример, так яснее.

Да спека - лишь рекомендация для движков. Ещё бы почитать доки по V8 со сборщиком мусора, хранением значений и т.д., но их нет =(

Соглашусь с @DmitryOlkhovoi, как я понял вы говорите, что переменные внутри функции уже в момент создания "знают" на что ссылаться. Хотя я увидел, другой механизм:

  • у объектов функций есть поле [[Environment]], оно ссылается на запись окружения в момент создания.

  • Потом при вызове функции, создаётся запись окружения этой функции, у которой поле [[OuterEnv]] будет ссылаться на запись из [[Environment]].

  • В итоге, лишь при выполнении, идя по цепочке записей окружения, мы найдём переменную. А не в момент создания.

Взял отсюда: 9.1.2.1 GetIdentifierReference ( env, name, strict ).

код на Bash взял из chatgpt, могу ошибаться =) хотел узнать какие языки решили проблему фунарга иначе.

Так да!

Scope, closure, block - это в хром девтулзах, а полез в спеку - таких слов вообще нет.

Отсутствие документации по V8 - боль!

Круто! Спасибо за справку.

[[Environment]] - это поле у объекта функции, оно ссылается на запись окружения.

[[OuterEnv]] - это поле у записи окружения, оно ссылается на родительскую запись окружения.

Это как я понял.

Да, согласен, можно копать ещё дальше. Поделился тем, что самому было интересно. Для джунов не умею писать.

Спасибо за критику. Исправил в статье все претензии по существу.

Остальное, ответы на комментарии:

что в общем-то никак не противоречит утверждению, что это функция, вернувшая функцию. Ну и не любой функции, а функции содержащей то самое определение. если есть функция foo() которая никак не связывается с bar(), которая в свою очередь содержит замыкание, то при создании foo замыкание в bar не будет создаваться.

без примера не могу понять связь этих функций. Я увидел, что по спеке JS не важно возвращается функция откуда-то или нет. "Замыкание", как механизм поиска идентификаторов (переменных внутри этой функции) есть всегда. Вернее сказать, что это особенность языка, выбор одного из решений проблемы фунарга.

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

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

В JS буквально почти всё объект. В том числе и функции. У не объекта не должно быть никаких полей или методов.

Функция – это объект, но "замыкание" - это механизм работы JS. Я это хотел подчеркнуть.

тут стоило бы пояснить, что такое внутренняя/внешняя переменная.

исправил ✅

нет, это не то же самое что и окружение. Окружение состоит из набора записей. И они вроеде как не могут быть вложенными, то есть под ключ записи нельзя положить какой-нибудь отдельный набор записей.

Я сократил название, чтобы было легче им оперировать. Да, окружения наследуются лишь через поле [[OuterEnv]]. "Environment Record is … used to define the association of Identifiers to… functions"

Какое окружение имеете в виду вы?

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

Не понял комментария. Да, самого слова "замыкание" нет в спеке. Поэтому и глагол "захватывает" можно использовать условно.

Захват контекста в функции зависит от записей окружения

Это я тоже не понял. Что значит контекст? Он отличается от записей окружения?

что значит "декларативное"? вы сделали тавтологию на ровном месте. Определение/объявление (англ. Declaration) функции оно и в африке им остаётся.

Простое объявление функции идёт в запись окружения через компонент VariableEnvironment, а FunctionExpression созданное через const идёт через LexicalEnvironment.

учитывая, что вся цепочка видимости, как и различные окружения - абстракция спеки, о чем вам написали парой абзацев выше, почему вы зовёте это РЕАЛИЗАЦИЕЙ?

исправил ✅

ничем она не управляет. this - это указатель объекта на себя и конструируется как часть объекта функции.

исправил ✅

откуда дровишки про рекурсию? оно не вызывает само себя, оно просто линейно проходит по списку.

исправил ✅.

Ещё раз спасибо. Я могу ошибаться.

1) Я попробовал написать статью с терминами спецификации: чтобы самому не путаться в "областях видимости", "скоупах", "блоках".

2) Я хотел максимально её визуализировать, чтобы самому что-то понять: вышло чёткое разделение Environmental Records и Lexical/Variable-Environment.

3) В документации learn.javascript.ru есть несколько "допущений", которые расходятся с EcmaScript и путают меня. Ведь V8 реализует EcmaScript, а не документацию learn.javascript.ru или блог MDN.

Примеры из документации learn.javascript.ru:

Устаревшее ключевое слово "var".

К сожалению, не нашёл слов depricated или прочих указаний, что это слово устарело =(

у каждой … функции, блока кода {...} … есть связанный с ними …скрытый объект - LexicalEnvironment. Он состоит из Environment Record и ссылки outer.

В начале статьи есть описание "блочной видимости", но после введения термина "LexicalEnvironment" такого примера уже нет. Остаётся неясным переход LexicalEnvironment от "объекта" функции к объекту блока.

4) Как и в пункте 1 я тоже путался. Что вы имеете в виду под _scope и OuterEnv?

[[OuterEnv]] я взял как поле, которое ссылается на родительскую запись окружения. 9.1 Environment Records

Спасибо, дописал уточнение про dynamic-range.

Information

Rating
Does not participate
Registered
Activity

Specialization

Фронтенд разработчик
Старший