Где хранится переменная в замыкании, в случае конструктора?
Допустим у нас есть код:
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 и находится через замыкание, то тогда эти два экземпляра должны мешать друг другу, перезаписывая значения друг друга. Если они не мешают друг другу, значит этот массив каким-то образом принадлежит объекту, но где "там" он лежит?...:-? Спасибо. |
Очень важно понимать в какой момент и почему происходит замыкание.
Сохранение всего лексического окружения в момент совершения определенного действия при исполнении кода. Тогда ответ станет очевидным. Конечно можно дать четкое и понятное разъяснение но это не поможет тебе разобраться в механике работы самой мощной в плане возможностей части JS. |
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 |
Код был приведён специально для того, чтоб задать вопрос по замыканию. В Ваших интерпритациях, SuperZen, никакого замыкания, нет, а значит и вопрос задавать не к чему...
|
Мужик, я могу понять таб в четыре пробела, хотя в два - гораздо приятней, но в десять? Зачем?
По вопросу: каждое исполнение функции имеет свой контекст. Каждое создание функции может замыкать переменные из вышестоящего контекста. При исполнении функции User создаётся контекст, в котором лежит fullArr. При исполнении функции User создаются новые функции-геттеры и функции-сеттеры, которые замыкают на себя вышестоящий контекст. |
Aetae
я правильно понимаю, что каждое исполнение функции, создаёт новые переменные и, если результаты этой функции, мы куда-то сохраняем (в какую-то внешнюю, по отношении к функции, переменную), то только эта переменная замыкается на конкретное исполнение функции? То есть, объект, на который ссылается переменная vasya, и объект, на который ссылается переменная masha, замыкается на конкретное исполнение User, поскольку каждое исполнение независимо и мы о них "помним" только потому, что у каждого из этих объектов, есть ссылка на свою переменную fullArr, сохранившуюся со времён исполнения функции User (при создании конкретного экземпляра объекта)? При этом, если мы избавимся от конструктора new: 1. уберём new перед переменными. 2. перед геттеро-сеттерами объявим новый объект var object = new Object (или просто = {} ). 3. вместо this в геттерах-сеттерах укажем object. 4. в конце функции вернём return object; то всё точно также будет работать, поскольку логика замыкания не изменится... Всё верно или есть ещё какие-то важные, для понимания, детали? Вы что-то говорили про контекст?... |
Вроде всё верно.
Цитата:
|
Ясненько. Спасибо, теперь, в общем-то ясно...
Получается у нас может быть относительно "простенький" объект, у которого 2,5 поля, а внутри тысячи внутренних переменных сложно регулирующих его поведение... А можно как-то выяснить, есть ли у объекта какое-то "двойное дно" или, стандартными средствами, это в общем-то, почти нереальная задача?... |
Launder, можно посмотреть в код.)
Ну или на растущую память. Нет таких задач где бы потребовалось отличать такой объект, потому что это не что-то особенное, а один и бесконечности вариантов написания кода. |
Спасибо всем откликнувшимся! Иногда понимаю, что не понимаю, или не достаточно понимаю, каких-то базовых вещей, поэтому придумываю какие-то достаточно простые примеры, чтоб работа какой-то технологии стала очевидной. Большое спасибо за наводки, вроде, в первом приближении, разобрался :)
|
Скажите а в чём смысл приватных свойств объекта, если их так легко можно реализовать через замыкания?...
|
Цитата:
class A { field1; field2; constructor () {...} meth1 () {...} meth2 () {...} } Где вы опишите переменную, которую "замыкает"? |
Ну отсюда второй вопрос возникает :) В каких ситуациях использования классов, прям уж так необходимо?...
У меня опыт маленький, поэтому, могу чего-то не понимать, но случаев, где я не увидел, как обычные функции полноценно заменяют классы(то есть прекрасно прописывают прототипные ссылки), было, вроде, всего два: Первое. Когда у нас есть родитель и его метод. И есть наследник, и его метод. И нужно (желательно), чтоб метод наследника назывался также, и содержал в себе уточнённое поведение метода родителя. В этом случае, да, классы удобнее. Второе. Когда изучал конструктор ошибок. Без классового синтаксиса с его super добиться нормального наследования, не получилось. Но опять же, я не слишком искушён, возможно, просто плохо себе представлял чего куда прописывать. А так, иногда создаётся впечатления, что классы, призванные сделать синтаксис более простым и прозрачным, на деле, таковым являются, для решения каких-то достаточно типовых задачах. А настраивать их сложнее... Вот, как раз, в случае с замыканиями. Хочу реализовать приватные свойства, с помощью замыканий они делаются на раз, а без них? Левой ногой через правое ухо :) |
Сейчас добавили для классов настоящие приватные свойства вида:
#<имя>, раньше просто писали _<имя>и соглашались, что мол свойства начинающиеся на _считаем приватными и не трогаем снаружи.) P.S. Лично меня, как адепта монкипатчинга, раздражают эти нововведения. Учитывая среднее качество гонокода в вебе, иметь возможность запатчить что-то внутри - насущная необходимость.) |
Цитата:
Да и то не полностью. Например, даже в хроме пока нет конструкции o?.#x Пока нет приватных методов. Я правда не очень понимаю такую уж большую необходимость введения приватных свойств. Защищенные (protected) были бы более насущными и востребованными. |
Какие аспекты программирования плохо реализовывать с помощью модулей? По-идее, всё закрыто, выводим только то, что считаем нужным, расширяем дополняем модифицируем... В чём минусы? Почему такой большой акцент на классы?
|
Модули - это модули, классы - это классы.
Классы нужны для ООП. О преимуществах ООП написаны гигабайты, гуглите. Модули нужны для удобства разделения кода, не важно ООП вы используете или функциональщину. |
Ну как бы одно квадратное, а другое зеленое.
Как модули без использования классов (функций конструкторов) помогут создавать объекты с методами, свойствами, наследованием...? |
Цитата:
Надо вот это прочитать, в этой же книге есть пример из предыдущей ссылки: https://addyosmani.com/resources/ess...patterns/book/ Introduction What is a Pattern? "Pattern"-ity Testing, Proto-Patterns & The Rule Of Three The Structure Of A Design Pattern Writing Design Patterns Anti-Patterns Categories Of Design Pattern Summary Table Of Design Pattern Categorization JavaScript Design Patterns Constructor Pattern Module Pattern Revealing Module Pattern Singleton Pattern Observer Pattern Mediator Pattern Prototype Pattern Command Pattern Facade Pattern Factory Pattern Mixin Pattern Decorator Pattern Flyweight Pattern JavaScript MV* Patterns MVC Pattern MVP Pattern MVVM Pattern Modern Modular JavaScript Design Patterns AMD CommonJS ES Harmony Design Patterns In jQuery Composite Pattern Adapter Pattern Facade Pattern Observer Pattern Iterator Pattern Lazy Initialization Pattern Proxy Pattern Builder Pattern jQuery Plugin Design Patterns JavaScript Namespacing Patterns Conclusions References Цитата:
Цитата:
|
Цитата:
class C { #x = 42; x(o = this){ return o?.#x; } } return new C().x() === 42 && new C().x(null) === void 0; Взят отсюда https://kangax.github.io/compat-table/esnext/ Насколько это реально нужно? Кто его знает Возможно такая фиговина может понадобится. |
ну походу еще не готово:
https://github.com/tc39/proposal-opt...ng#open-issues меньше букав придется писать ) |
Launder,
Синтаксис модулей и классов был принят в стандарт JS в 2015 году. До этого как-то без них 20 лет жили. Классы в основном просто более удобный синтаксис для функций-конструкторов - From constructors to classes. Модули - порождение развития сторонних модульных систем - From CommonJS modules to ES6 modules. Функции-конструкторы тоже обзывают классами. Не стоит от JS ожидать полноценного класса C++. Приватные свойства приняты в 2019-м. До этого как-то без них 30 лет жили. Бог знает, что нам еще предстоит испытать... Классы - это свои типы данных. Модули - организация проекта. |
Прошу прощения за задержки, разбираюсь наскоками, тестирую возможности модулей. Выразился некорректно - я имел в виду, не синтаксис модулей в ES2015 а паттерн программирования "модуль" (пример, на базе которого экспериментирую взят отсюда,) после заголовка "современные модули". Возможно между ними есть что-то общее (судя, например, по закрытой зоне видимости и инициализации, после которой один и тот же набор переменных, для любого импорта, что-то общее есть), но насколько совпадения полное - не знаю.
А сравниваю с классами вот почему, классы, по сути, не имеют (общих) переменных, а имеют поля, а модули, через замыкания, могут иметь, по-видимому, практически неограниченную сложность внутри, при этом по-умолчанию, доступно только то, что мы сделаем доступным (вероятно, доступным можем сделать всё). Вы пишите "это просто разное", вот и пытаюсь разобраться, что вообще можно делать с помощью модулей и насколько это удобно для возможных изменений/расширений и ввода/вывода. Универсальность подхода, и его "естественные ограничения"... |
Цитата:
Цитата:
|
Много у современных модулей общего с паттерном программирования "модуль", ссылку на пример из книги, в качестве иллюстрации, приводил выше?...
|
Часовой пояс GMT +3, время: 06:38. |