Объектно-ориентированный JavaScript

closure

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

lexical scope

  • Лексическая область видимости означает, что структура самого кода определяет, где можно получить доступ к переменной. Другими словами, области неявно создаются на основе вложенности кода. Исходный код содержит иерархию областей, вплоть до глобальной области.
  • JavaScript сначала ищет переменную в локальной области видимости, а затем вверх по уровням, пока не достигнет конечной глобальной области видимости. Вот почему может происходить переменное затенение.

private data

  • Выражение функции с немедленным вызовом (IIFE) создает частную область, которая не конфликтует ни с какой другой областью, и вызывается немедленно. В результате данные в частной области недоступны где-либо еще.
  • Введение let и const в ES6 сделало IIFE менее полезными для создания частной области.
  • IIFE также можно использовать для создания частных данных из-за того, как работают замыкания.
  • Приложение с частичной функцией требует меньшего количества аргументов, передаваемых внутренней функции при ее вызове, чем это было бы необходимо в противном случае. Обычно один из аргументов сначала передается внешней/обертывающей функции. Этот аргумент, если на него ссылается внутренняя/возвращаемая функция, таким образом фиксируется в замыкании внутренней/возвращаемой функции. Но на аргумент нельзя ссылаться вне самой функции, что делает данные закрытыми. В результате приложения с частичной функциональностью используют замыкания для сокрытия данных.
  • Частичные приложения функций также полезны, когда нам нужно вызвать функцию несколько раз с одним и тем же аргументом (аргументами).
  • Мы можем использовать тело функции для приватизации данных: переменная, инициализированная в теле функции, которая ссылается на данные, которые не передаются в функцию и не возвращаются функцией, по своей сути недоступна вне функции и, следовательно, закрыта.

this

  • Ключевое слово, которое ссылается на контекст выполнения функции.
  • Вне функции или метода контекстом выполнения функции является глобальный объект (window в браузере) или undefined в строгом режиме (без доступа к глобальному объекту).
  • Внутри функции контекст выполнения зависит от контекста вызова функции.
  • Стрелочные функции являются исключением: контекстом выполнения является объемлющий лексический контекст. Кроме того, стрелочные функции не имеют свойства prototype, поэтому их нельзя вызывать с оператором new и использовать в качестве функции-конструктора.
  • Внутри метода контекст выполнения — это объект, свойством которого является метод.
  • Функция, вложенная в метод, является обычной функцией, а не методом: ее контекстом выполнения по умолчанию является глобальный объект.
  • Методы могут быть «отделены» от их объектов, когда они не вызываются для самого объекта: сам метод может быть назначен переменной или передан как параметр, и в этом случае он больше не вызывается как метод, а как функция.

explicit execution context

  • Явный контекст выполнения переопределяет неявный контекст выполнения.
  • call, apply и bind используются для установки явного контекста выполнения функции.
  • call принимает явный контекст выполнения в качестве аргумента 1 и n последующих аргументов и выполняет функцию в контексте аргумента 1 после передачи последующих аргументов в функцию.
  • apply принимает явный контекст выполнения в качестве аргумента 1 и массив в качестве второго аргумента и выполняет функцию в контексте аргумента 1 после передачи второго аргумента в функцию.
  • bind принимает явный контекст выполнения в качестве аргумента 1 и n последующих аргументов и возвращает новую функцию, постоянно связанную с явным контекстом выполнения аргумента 1.

managing context loss

  • Желаемый контекст выполнения легко теряется, потому что контекст определяется при вызове (если мы не установили явный контекст выполнения).
  • call, apply или bind можно использовать для установки или сохранения желаемого контекста выполнения.
  • Переменная может быть инициализирована для ссылки на контекст выполнения желания, а затем на нее можно ссылаться во внутренней области, которая не имеет желаемого контекста, в качестве замены для this.
  • Необязательный аргумент thisArg, доступный для некоторых методов, которые принимают аргументы функции, может использоваться для передачи в желаемом контексте выполнения.
  • Ссылка на желаемый контекст выполнения может быть передана вызову функции в качестве аргумента.

garbage collection

  • JavaScript выделяет память и имеет сборку мусора во время выполнения, избавляя нас от написания подверженного ошибкам кода, который выделяет и освобождает память.
  • Сборка мусора важна, поскольку освобождение памяти освобождает память, которую затем можно использовать в другом месте программы.
  • Сборка мусора JS больше не может запускаться разработчиками. Вместо этого это происходит в разных точках программы по мере ее выполнения.
  • Память делится на две категории: стек и куча.
  • Стек: примитивы (кроме String и BigInt) и указатели. Они не имеют права на вывоз мусора. В стеке используется другая система «распределения и освобождения», основанная на знании фиксированного размера каждого элемента в памяти.
  • Куча: Массивы, строки и объекты, например, подходят для сборки мусора. Это объекты без фиксированного размера. Они хранятся в куче до тех пор, пока на них есть ссылки в программе: значение кучи удаляется сборщиком мусора только тогда, когда его счетчик ссылок равен нулю.
  • Примечательно, что значения кучи, доступные внутри замыкания, не могут быть удалены сборщиком мусора до тех пор, пока переменная, ссылающаяся на замыкание, не будет переназначена или пока программа не завершится и все значения не будут удалены сборщиком мусора. Один трюк состоит в том, чтобы переназначить переменную, которая ссылается на замыкание, на null, чтобы явно завершить/удалить замыкание.
  • Ссылки в замыкании подсчитываются по отношению к количеству ссылок значения в куче. Пока существует замыкание, значения, на которые он ссылается, не могут быть удалены сборщиком мусора.
  • Алгоритмы Mark и Sweep используются современными JS-движками для сборки мусора. Положительным моментом является то, что маркировка и развертка улавливают циклы круговых ссылок. Недостатком является то, что это может привести к фрагментации памяти, что затрудняет выделение памяти.

factory object creation pattern

  • Функции можно использовать для возврата объектов со свойствами, которые были определены внутри функции, что делает функцию шаблоном для объектов.
  • Два недостатка: (1) нет возможности идентифицировать источник или шаблон объектов, возвращаемых фабричной функцией, из самого объекта (2) каждый объект, созданный фабричной функцией, имеет свою собственную копию методов, определенных внутри функции, так что есть дублирование.

pseudo-classical pattern (constructor)

  • Псевдоклассический паттерн достигается за счет использования функции в качестве конструктора в сочетании с оператором new.
  • Функции, используемые в качестве конструкторов, обычно обозначаются именами, написанными с заглавной буквы.
  • Когда new вызывает функцию как конструктор, выполняются пять шагов:
    (1) Создается новый объект
    (2) Свойство prototype конструктора является [[Prototype]] нового объекта (но не [[Prototype]] конструктора). )
    (3) this внутри конструктора ссылается на новый объект (вместо глобального объекта, что обычно происходит)
    (4) Выполняется код в теле функции конструктора
    ( 5) this возвращается неявно, если конструктор явно не возвращает объект
  • Каждая функция, кроме стрелочных, имеет свойство prototype. Это свойство ссылается на объект со свойством constructor, которое, в свою очередь, ссылается на функцию-конструктор.
  • Мы должны определить свойства, которые не должны быть уникальными для возвращаемого объекта в объекте-прототипе конструктора, а не в теле функции-конструктора, чтобы среда выполнения не создавала свойство заново каждый раз, когда объект создается из конструктора.

pseudo-classical pattern (class)

  • Псевдоклассический шаблон достигается за счет использования синтаксиса класса ES6.
  • Ключевое слово class используется вместо определения функции-конструктора.
  • Объекты создаются с помощью оператора new.
  • Функция constructor (которую мы можем создать) внутри класса работает как обычная функция-конструктор. Он используется для установки уникального состояния каждого объекта, созданного из класса. Аргументы, переданные классу после new, затем передаются функции constructor.
  • Функции в основном теле класса, вне constructor функции, становятся методами prototype всех объектов, созданных из класса.
  • Классы - граждане первого класса.
  • Код в объявлении класса выполняется в строгом режиме.
  • Поднимаются имена классов, но не значение, поэтому оно может находиться в TDZ.
  • Мы не можем переназначить прототип класса.
  • Мы не можем вызвать конструктор класса без оператора new.
  • Этот синтаксис понятен и с ним проще работать, особенно когда мы хотим создать цепочки прототипов: создание прототипа конструктора, наследуемого от другого прототипа конструктора, запутанно и сложно по сравнению с синтаксисом класса, в котором используется ключевое слово extends, чтобы сделать класс наследованием от другого.
  • Ключевое слово super вызывает следующую одноименную функцию в цепочке прототипов и должно использоваться перед вызовом this.
  • super чаще всего используется в методе конструктора подкласса.

objects linked to other objects pattern (OLOO)

  • Самый простой способ формирования цепочек прототипов.
  • Шаблон OLOO не навязывает JS поддельную систему классов.
  • Шаблон использует ключевое слово create для создания одного объекта из другого объекта, что автоматически устанавливает уже существующий объект в качестве прямого [[Prototype]] нового объекта.
  • Методы init обычно определяются в объектах-прототипах и связываются с вызовами create, так что аргументы могут передаваться во время создания экземпляра объекта и использоваться для установки нового состояния объекта.
  • Методы в объекте шаблона/прототипа становятся поведением, унаследованным объектами, созданными из объекта шаблона.

methods

Object.create(исходный объект)
возвращает новый объект, прототипом которого является исходный объект.

Object.setPrototypeOf(object, newPrototype)
медленный, неэффективный, вместо этого используйте create

Object.getPrototypeOf(object)
возвращает объект прямого прототипа (следующий вверх по цепочке прототипов)

object1.isPrototypeOf(object2)
возвращает логическое значение, проверяет, входит ли объект1 в цепочку прототипов объекта2

Object.hasOwnProperty(propertyName)
возвращает логическое значение, проверяет ключи, определенные на объекте напрямую (не унаследованные)

Object.getOwnPropertyNames(object)
возвращает массив ключей, определенных непосредственно на объекте (не наследуется)

оператор object instanceof Constructor
, возвращает логическое значение, проверяет наличие прототипа Constructor в цепочке прототипов объекта

Оператор новый Конструктор
, возвращает новый объект, который наследуется от объекта-прототипа Конструктора.

Object.freeze(object)
после вызова этого метода мы не можем изменять свойства, не являющиеся объектами, и замороженное состояние нельзя отменить.

Object.defineProperties(object, {
может использоваться для определения новых свойств непосредственно в объекте, доступном только для чтения

Кроме того, у объектов есть свойство __proto__, которое ссылается на [[Prototype]].