function Foo(){
var someObj = {
s: 'string'
}
console.info(someObj.s);
}
Foo(); // first call
Foo(); // second call
Будет ли память, на которую указывает someObj
, будет перезаписана или будет выделена новая? Если будет выделена новая память, что произойдет с someObj
, созданным при первом вызове, сотрет ли его сборщик мусора? И должен ли я сделать определение someObj
вне функции, чтобы уменьшить количество операций с памятью?
При каждом вызове someObj
будет создаваться новый Foo
. Вы можете проверить это, вернув объект и посмотрев, равен ли новый:
function Foo(){
var someObj = {
s: 'string'
};
return someObj;
}
console.info(Foo() === Foo());
Они не совпадают — место в памяти, на которое указывает первый someObj
, не совпадает с местом в памяти, на которое указывает второй someObj
. Если вы постоянно вызываете Foo
, не оставляя времени для запуска сборщика мусора, в конечном итоге у вас закончится память.
Если объект не возвращается, то после запуска Foo
ничто другое не может ссылаться на someObj
, поэтому вскоре он будет подвергнут сборке мусора.
Если вы хотите предотвратить создание нескольких someObj
, да, не стесняйтесь определять someObj
вне Foo
.
Если вы хотите, чтобы на someObj
можно было ссылаться только внутри Foo
, а также создавать только один такой объект, тогда превратите Foo
в IIFE:
const Foo = (() => {
var someObj = {
s: 'string'
};
return () => {
console.info(someObj.s);
};
})();
Foo();
If you want someObj to only be referenceable inside of Foo while also creating only one such object, then turn Foo into an IIFE
а можно подробнее эту строчку? я не думаю, что мы можем получить доступ к someObj
вне функции даже в коде OP
Верно, к нему нельзя получить доступ извне, но он все равно создается ровно один раз, когда запускается IIFE. Он также может быть возвращен из внутренней функции, если вы хотите, но для чего-то постоянного, что не имеет большого смысла в большинстве ситуаций IMO
Насколько я понимаю, меня это не волнует при написании js. Компилятор (V8 или что-то еще, компилирующее ваш код) должен выполнить необходимую оптимизацию.
Но:
Will the memory where the someObj points to are overwritten or will a new one be allocated?
Я говорю, что он выделяется каждый раз, когда вызывается функция. Или, другими словами, вы можете все время рассматривать его как новую переменную.
what happens with someObj created at first call, will garbage collector erase it
Да, когда функция вызывается и завершается, эта ссылка помечается как мусор, который должен быть очищен сборщиком мусора при запуске сборщика мусора.
And should I make a definition of someObj outside the function to reduce the number of memory operations?
Из моих знаний о V8 и подобных, если тип всегда один и тот же, есть некоторые встроенные методы, которые сделают эту оптимизацию.
Однако в целом я не могу себе представить, как часто это нужно будет вызывать, что вам понадобится какая-то оптимизация в таком коде.
Этот вопрос звучит либо как академическая проблема (с которой я, вероятно, мало чем могу помочь), либо как попытка преждевременной оптимизации.
В качестве примечания. Код в первую очередь для других людей. Он должен быть удобочитаемым для них в первую очередь.
Эта функция вызывается около 80 000 раз, а объект больше, поэтому я так беспокоюсь о таких вещах.
Я бы не стал выводить эту переменную из области действия функций, если бы не был на 100% уверен, что это не приведет к условиям гонки со странной асинхронностью. Но сделайте свои тесты и посмотрите, даст ли это вам какие-либо преимущества.
Он будет заново выделяться каждый раз, когда вы вызываете функцию, когда вы вызываете функцию, она каждый раз создает новый контекст в стеке выполнения, и как только функция возвращает управление обратно, этот контекст будет выскакивать из стека выполнения.