Потребляет ли создание функций больше памяти
// Case A
function Constructor() {
this.foo = function() {
...
};
...
}
// vs
// Case B
function Constructor() {
...
};
Constructor.prototype.foo = function() {
...
}
Одна из главных причин, по которой люди советуют использовать прототипы, заключается в том, что .foo
создается один раз в случае прототипа, где as this.foo
создается несколько раз при использовании другого подхода.
Однако можно было бы ожидать, что интерпретаторы могут оптимизировать это. Так что существует только одна копия функции foo
в случае A.
Конечно, вы все равно будете иметь уникальный контекст области для каждого объекта из-за замыканий, но это имеет меньше накладных расходов, чем новая функция для каждого объекта. объект.
Оптимизируют ли современные интерпретаторы JS случай A таким образом, что существует только одна копия функции foo
?
3 ответа:
Да, создание функций требует больше памяти.
... и нет, интерпретаторы не оптимизируют регистр A до одной функции.
Причина в том, чтоцепочка областей JS требует, чтобы каждый экземпляр функции захватывал переменные, доступные ему в момент ее создания. Тем не менее, современные интерпретаторы лучшео случае а, чем они были раньше, но в основном потому, что выполнение функций замыкания было известной проблемой пару лет назад. тому назад.
По этой причине Mozilla советует избегать ненужных замыканий, но замыкания являются одним из самых мощных и часто используемых инструментов в инструментарии разработчика JS.Update: Только что запустил этот тест, который создает 1M "экземпляров" конструктора, используя узел.js (то есть V8, интерпретатор JS в Chrome). С помощью
caseA = true
я получаю следующее использование памяти:{ rss: 212291584, vsize: 3279040512, heapTotal: 203424416, heapUsed: 180715856 }
И с
caseA = false
я получаю это использование памяти:{ rss: 73535488, vsize: 3149352960, heapTotal: 74908960, heapUsed: 56308008 }
Таким образом, функции замыкания определенно потребляя значительно больше памяти, почти в 3 раза, но в абсолютном смысле мы говорим только о разнице ~140-150 байт на экземпляр. (Однако это, скорее всего, увеличится в зависимости от количества переменных в области действия, которые будут у вас при создании функции).
Я полагаю, после некоторого краткого тестирования в узле, что в обоих случаях A и B существует только одна копия фактического кода для функции
foo
в памяти.Случай A-существует объект функции, созданный для каждого выполнения
Constructor()
, хранящий ссылку на код функции и ее текущую область выполнения.Случай B - существует только одна область видимости, один объект функции, совместно используемый через прототип.
Интерпретаторы javascript также не оптимизируют объекты-прототипы. Это просто случай, когда существует только один из них на тип (ссылка на несколько экземпляров). Конструкторы, с другой стороны, создают новые экземпляры и методы, определенные в них. Таким образом, по определению, это действительно не вопрос "оптимизации" интерпретатора, а просто понимания того, что происходит.
В качестве дополнительной заметки, если интерпретатор попытается объединить методы экземпляра, вы будете столкнетесь с проблемами, если вы когда-нибудь решите изменить значение единицы в конкретном случае (я бы предпочел, чтобы головная боль не добавлялась в язык):)