Как стать автором
Обновить

Комментарии 26

Большое спасибо за статью! Недавно как раз начал изучать JS. Узнал про методы копирования объекта через Object.assign и JSON.parse(...), но мне показалось что и то и то работает криво.. А вот structuredClone теперь буду применять на практике

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

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

Это как ? Вряд ли вы сможете объявить переменную именно в более высоком скопе (не считая момента, чио после появления let у нас два скопа теперь, и можно сказать , что объявляя var в фигурных скобочках мы выходим за скоп, но это как то жиденько), а не свойство объекта window (или global), что и во многих других языках вполне легально.

Наверно, речь про то, что если не в строгом режиме присвоить значение несуществующей переменной, то она создается в глобальном скоупе. В строгом это будет ошибка.

Верно, спасибо за уточнение

Правда в том, что она не создается в этом скопе, т.к. в таком случае она присвоится window (в отличии от объявления с помошью var, в верхнем скопе) и обращение к ней пойдет по схеме "нет ни в одном в скопе, а есть ли свойство window ?", Т.е. это не переменная, а такой способ объявления, просто сахар для обращения к window.

И да, уже много лет рекомендуется всегда использовать "use strict", чтобы выключить это "фичу" от тех времён, когда никому не могло придти в голову, что нацдутся сумасшедшие, которые будут несколько раз в минуту качать приложения по. 100кб и запускать их на клиентских устройствах. Интересно, как в minitel фронтенд был сделан, кто нибудь знает ?

Вы сильно напутали.

Вне зависимости от strict или nonstrict режима, все идентификаторы заявляемые при помощи var statement или hoistable declaration в рамках Global Environment будут созданы как Named Property в текущем Global Object. (Тем кто не в курсе, JavaScript допускает любое количество глобальных обьектов)

Если говорить "простым" языком то все var и все function обьявленые в том, что привыкли называть глобальной областью видимости ( Global Environment) будут определены как named property для текущего глобального обьекта. То что Вы назвали window - это один из вариантов глобального обьекта создаваемого HOST средой браузера. window это не единсвенный глобальный обьект в браузере. Их там разных почти 7 штук. window - это тот, который привыкли видеть чаще всего.

В случае выполнения assignment expression (то что безграмотно привыкли называть присвоение переменной), произойдет поиск идентификатора по цепочке Environment ( то что безграмотно привыкли называть областями видимости) и в случае если поиск по цепочке приведет к Environment Record у которой [[OuterEnv]] будет связано с null (то что привыкли безграмотно называть глобальной областью видимости) произойдет проверка в каком режиме strict или nonstrict выполнялось assignment expression.

В strict режиме мы получим throw complition. В non strict режиме произойдет инициализация named property у Global Object после чего с ним будет связано значение из assignment expression.

Говоря безграмотным языком - в non strict режиме, присваивание переменной без var statement эквивалентно var statement в глобальной области видимости.

Иными словами, все variable declaration вне зависимости от strict режима, которые инициализируются в глобальной области видимости - приведут к созданию named property в текущем global object.

Описанное мной выше, является упрощенным пересказом официальной спецификации ECMA.

Так ужасная проблема js по мнению OP, как раз в том, что можно декларировать переменные в "глобальной" области из дочерних скопов. Мой комментарий был, что это не совсем так на самом деле во первых, а во вторых, что use strict это отключает. Первая часть вашего коментария в основном повторяет мои тезисы, а вторая указывает на несуществующую в них ошибку.

Кроме того, объявления с let или const не станут свойством глобального объекта (я кажется в прошлый раз забыл упомянуть что window, бывает global и вообще от платформы зависит) , т.е. не "все".

Если честно, при всей несовершенности js, меня всегда удивляют такие "открытия" от незнания особенностей языка, на cpp, например вообще писать нельзя с таким подходом, т.к. там костыли ещё и многомерные. Часто ещё как минус упоминается "отсутствие типов", прр этом конечно все забывают, что именно эта штука позволяет написать и запустить прототип приложения за 5 минут, вместо 2х часов. И что ещё более важно, позволяет сделать этот прототип людям, основная деятельность которых далека от it.

Ниже уже более детально пояснили. Но в целом JS мне нравится своей простотой. На нём можно чё-то быстро налабать, и будеть работать

Но работать будет не правильно, поэтому придётся долго-долго отлаживать.

Это не от языка зависит. А от программиста и задачи.

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

Именно по єтой причине в JS можно складывать все и со всем. Поскольку предполагается, что программист самостоятельно определит нужное ему поведение.

Как и оперирование идентификаторами.

А что с ним не так?

Можно подробнее пожалуйста? Или скажите тему почитать. Интересна Ваша идея

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

Ну так то да. Заметил, что я за три с половиной года(весь мой опыт, так что прошу строго не судить) ни разу и не копировал объекты глубоко, кроме одного момента.

Вот есть форма редактирования чего-либо. Вот мы ее открываем и закидываем в поля глубоко скопированные данные чтобы их там в форме менять и т.д. Но в уме(любое js хранилище) держим оригинал, что бы иметь возможность сделать to_default_state_action. Это наверное единственное место, где я пока не могу придумать как обойтись без глубокого копирования.

Как бы Вы поступили в данном случае?

Много вариантов:

  • Copy-On-Write прокси.

  • Писать в отдельный объект, читать из обоих.

  • Хранить изменённое состояние в компонентах, при сабмите собирать и посылать, при ресете ререндерить.

Мб я не дополнял, но по моему я иду всегда по третьему Вашему пункту :) я считаю это за глубокое копирование, да это не вызов cloneDeep, но все таки это парсинг данных из оригинала в состояние формы, которое все таки повторяет структуру оригинала(не всегда, но часто). По итогу и выйдет, что есть оригинал и его копия в форме. Я не прав ? Если да, то поправьте плз

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

const shallowCopy = Object.create(obj);

разумеется, это никакой не shallowCopy.

const obj = {x: 1};
const shallowCopy = Object.create(obj);
obj.x = 2;
console.log(shallowCopy.x); // 2

Метод structuredClone может выполнять следующие задачи:

- Клонировать бесконечно вложенные объекты и массивы;

За бесконечное время? )

Зарегистрируйтесь на Хабре, чтобы оставить комментарий