Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Где хранится переменная в замыкании, в случае конструктора? (https://javascript.ru/forum/misc/80506-gde-khranitsya-peremennaya-v-zamykanii-v-sluchae-konstruktora.html)

Launder 14.06.2020 12:08

Где хранится переменная в замыкании, в случае конструктора?
 
Допустим у нас есть код:
function User(fullName)
	{
          var fullArr = fullName.split(' ');  //делаем массив
          
          Object.defineProperty(this, 'firstName',          
          		{
              		       get: function()
                   		    {
                              		 return fullArr[0]; //выдаём первый элемент массива
                                    },
                               set: function(value)
                   		    {
                              		 fullArr[0] = value; // записываем первый элемент массива
                                    }

                        } );
          Object.defineProperty(this, 'lastName',          
          		{
              		       get: function()
                   		    {
                              		 return fullArr[1]; //выдаём второй элемент массива
                                    },
                               set: function(value)
                   		    {
                              		 fullArr[1] = value; //записываем второй элемент массива
                                    }
                         } );
          Object.defineProperty(this, 'fullName',          
          		{
              		       get: function()
                   		    {
                              		 return fullArr[0] + ' ' + fullArr[1]; //выдаём весь массив, через пробел
                                    },
                               set: function(value)
                   		    {
                                         fullArr = value.split(' '); //записываем массив из строки
                                    }
                         } );
	}

var vasya = new User("Василий Тёркин");
var masha = new User("Мария Шарапова");

Итак у нас два разных пользователя. Они, насколько я понимаю, ничем друг другу не мешают. Но мне до конца не понятен механизм их образования: оператор new генерирует создание нового объекта, функция выполняется и выдаёт этот новый объект. Но! Массив fullArr где хранится? если он лежит в функции(конструкторе) User и находится через замыкание, то тогда эти два экземпляра должны мешать друг другу, перезаписывая значения друг друга. Если они не мешают друг другу, значит этот массив каким-то образом принадлежит объекту, но где "там" он лежит?...:-? Спасибо.

MallSerg 14.06.2020 12:36

Очень важно понимать в какой момент и почему происходит замыкание.
Сохранение всего лексического окружения в момент совершения определенного действия при исполнении кода.
Тогда ответ станет очевидным.

Конечно можно дать четкое и понятное разъяснение но это не поможет тебе разобраться в механике работы самой мощной в плане возможностей части JS.

SuperZen 15.06.2020 11:50

function User(fullName) {
  this.fullArr = fullName.split(' ')
}

User.prototype = {
  get firstName() {
    return this.fullArr[0];
  },
  set firstName(value) {
    this.fullArr[0] = value;
  },
}

// или

// Object.defineProperty(User.prototype, 'firstName', {
//   get: function () {
//     return this.fullArr[0];
//   },
//   set: function (value) {
//     this.fullArr[0] = value;
//   },
// })


Вообще код должен был выглядеть примерно так... почему? :)

https://github.com/azat-io/you-dont-...%D0%B8%D 1%8F

https://github.com/azat-io/you-dont-...ect-prototypes

https://github.com/azat-io/you-dont-know-js-ru

Launder 18.06.2020 14:18

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

Aetae 18.06.2020 15:17

Мужик, я могу понять таб в четыре пробела, хотя в два - гораздо приятней, но в десять? Зачем?

По вопросу: каждое исполнение функции имеет свой контекст. Каждое создание функции может замыкать переменные из вышестоящего контекста.

При исполнении функции User создаётся контекст, в котором лежит fullArr. При исполнении функции User создаются новые функции-геттеры и функции-сеттеры, которые замыкают на себя вышестоящий контекст.

Launder 18.06.2020 18:57

Aetae
я правильно понимаю, что каждое исполнение функции, создаёт новые переменные и, если результаты этой функции, мы куда-то сохраняем (в какую-то внешнюю, по отношении к функции, переменную), то только эта переменная замыкается на конкретное исполнение функции?
То есть, объект, на который ссылается переменная vasya, и объект, на который ссылается переменная masha, замыкается на конкретное исполнение User, поскольку каждое исполнение независимо и мы о них "помним" только потому, что у каждого из этих объектов, есть ссылка на свою переменную fullArr, сохранившуюся со времён исполнения функции User (при создании конкретного экземпляра объекта)?
При этом, если мы избавимся от конструктора new:
1. уберём new перед переменными.
2. перед геттеро-сеттерами объявим новый объект var object = new Object (или просто = {} ).
3. вместо this в геттерах-сеттерах укажем object.
4. в конце функции вернём return object;

то всё точно также будет работать, поскольку логика замыкания не изменится...
Всё верно или есть ещё какие-то важные, для понимания, детали?
Вы что-то говорили про контекст?...

Aetae 18.06.2020 19:09

Вроде всё верно.
Цитата:

о них "помним" только потому, что у каждого из этих объектов, есть ссылка на свою переменную fullArr, сохранившуюся со времён исполнения функции User
А сохранилась она потому, что во время исполнения были созданы новые функции, которые использовали эту переменную. Иначе GC бы просто очистил от неё память, т.к. на неё не осталось бы ссылок.

Launder 20.06.2020 20:24

Ясненько. Спасибо, теперь, в общем-то ясно...
Получается у нас может быть относительно "простенький" объект, у которого 2,5 поля, а внутри тысячи внутренних переменных сложно регулирующих его поведение...
А можно как-то выяснить, есть ли у объекта какое-то "двойное дно" или, стандартными средствами, это в общем-то, почти нереальная задача?...

Aetae 21.06.2020 07:11

Launder, можно посмотреть в код.)
Ну или на растущую память.

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

Launder 21.06.2020 15:04

Спасибо всем откликнувшимся! Иногда понимаю, что не понимаю, или не достаточно понимаю, каких-то базовых вещей, поэтому придумываю какие-то достаточно простые примеры, чтоб работа какой-то технологии стала очевидной. Большое спасибо за наводки, вроде, в первом приближении, разобрался :)


Часовой пояс GMT +3, время: 21:50.