function foo(a) {
if (/* Some condition */) {
// perform task 1
// perform task 3
}
else {
// perform task 2
// perform task 3
}
}
У меня есть функция, структура которой аналогична приведенной выше. Я хочу абстрагировать задачу 3 в функцию, bar()
но я хочу ограничить доступ этой функции только в рамках foo(a)
.
Правильно ли переходить к следующему, чтобы достичь того, чего я хочу?
function foo(a) {
function bar() {
// Perform task 3
}
if (/* Some condition */) {
// Perform task 1
bar();
}
else {
// Perform task 2
bar();
}
}
Если приведенное выше верно, bar()
переопределяется ли каждый раз при foo(a)
вызове? (Здесь меня беспокоит потеря ресурсов ЦП.)
javascript
Тамаки
источник
источник
Ответы:
Да, то, что у вас есть, правильно. Некоторые примечания:
bar
создается при каждом вызове функцииfoo
, но:bar
, что происходит, некоторые движки могут определить, что они могут «встроить» его, полностью исключив вызов функции. V8 делает это, и я уверен, что это не единственный двигатель. Естественно, они могут это сделать, только если это не изменит поведение кода.bar
создания каждый раз будет широко варьироваться в зависимости от движка JavaScript. Еслиbar
это тривиально, оно будет варьироваться от необнаружимого до довольно маленького. Если вы не звонитеfoo
тысячи раз подряд (например, изmousemove
обработчика), я бы не стал беспокоиться об этом. Даже если да, я бы беспокоился об этом, только если бы увидел проблему с более медленными двигателями. Вот тестовый пример, связанный с операциями DOM , который предполагает, что влияние есть, но тривиально (вероятно, смыто материалом DOM). Вот тестовый пример, выполняющий чистые вычисления, который показывает гораздо большее влияние, но, честно говоря, даже мы говорим о разнице в микросекунды, потому что даже 92% -ное увеличение того, что требует микросекунды - это еще очень и очень быстро. До тех пор, пока вы не увидите столкновения в реальном мире, не о чем беспокоиться.bar
будет доступен только изнутри функции, и он имеет доступ ко всем переменным и аргументам для этого вызова функции. Это делает этот шаблон очень удобным.источник
bar
создается при каждом вызовеfoo
)foo
. Если вы не звонитеfoo
тысячи раз подряд (например, не вmousemove
обработчике), я бы вообще не беспокоился об этом. И обратите внимание, что некоторые движки (например, V8) все равно встраивают код, полностью исключая вызов функции, при условии, что это не меняет происходящего таким образом, чтобы его можно было обнаружить извне.bar()
каждом вызове? Кроме того, поможет ли использованиеfoo.prototype.bar
для определения функции?bar
есть доступ к переменным и аргументам для вызоваfoo
(все, что вы хотите, чтобы он работал, вы должны передать это), что может немного усложнить ситуацию, но в критической для производительности ситуации, когда вы Если вы заметили реальную проблему, вы можете провести подобный рефакторинг, чтобы увидеть, решит ли это проблему. Нет, использование наfoo.prototype
самом деле не поможет (во-первых,bar
больше не будет закрытым).Вот для чего нужны закрытия.
var foo = (function () { function bar() { // perform task 3 }; function innerfoo (a) { if (/* some cond */ ) { // perform task 1 bar(); } else { // perform task 2 bar(); } } return innerfoo; })();
Innerfoo (замыкание) содержит ссылку на bar, и только ссылка на innerfoo возвращается из анонимной функции, которая вызывается только один раз для создания замыкания.
Таким образом, бар недоступен снаружи.
источник
var foo = (function () { var bar = function () { // perform task 3 } return function (a) { if (/*some condition*/) { // perform task 1 bar(); } else { // perform task 2 bar(); } }; }());
Замыкание сохраняет область
bar()
содержания, возвращая новую функцию из самоисполняющейся анонимной функции, устанавливает более видимую область видимостиfoo()
. Анонимная самовыполняющаяся функция запускается ровно один раз, поэтому существует только одинbar()
экземпляр, и каждое выполнениеfoo()
будет использовать его.источник
Да, отлично работает.
Внутренняя функция не воссоздается каждый раз, когда вы вводите внешнюю функцию, но она переназначается.
Если вы протестируете этот код:
function test() { function demo() { alert('1'); } demo(); demo = function() { alert('2'); }; demo(); } test(); test();
она покажет
1
,2
,1
,2
, не1
,2
,2
,2
.источник
demo()
каждого времениtest()
проблемой производительности? Это зависит от сложностиdemo()
?Я создал jsperf для тестирования вложенных и невложенных, а также функциональных выражений и объявлений функций, и я был удивлен, увидев, что вложенные тестовые примеры выполняются в 20 раз быстрее, чем невложенные. (Я ожидал либо противоположных, либо незначительных различий).
https://jsperf.com/nested-functions-vs-not-nested-2/1
Это в Chrome 76, macOS.
источник