Здравствуйте,помогите разобраться почему Function Declaration объявленная в цикле,создается на каждой итерации.
Из https://learn.javascript.ru/function-declaration-expression
Основное отличие между ними: функции, объявленные как Function Declaration, создаются интерпретатором до выполнения кода.
var arr = [];
for (var i = 0; i < 5; i++) {
function example() {}
example.i = i;
arr.push(example);
}
console.log(arr);
Вопрос возник когда разбирался с NFE которые создаются в процессе выполнения выражения.
На самом деле в конкретном примере нет абсолютно никакой разницы, используется ли функциональное объявление или функциональное выражение:
var arr = [];
for (var i = 0; i < 5; i++) {
function example() {}
example.i = i;
arr.push(example);
}
console.log(arr[0] === arr[1]); // === arr[2] === ... => false
var arr = [];
for (var i = 0; i < 5; i++) {
var f = function example() {};
f.i = i;
arr.push(f);
}
console.log(arr[0] === arr[1]); // === arr[2] === ... => false
В обоих случаях идентификатор будет перезаписываться. В первом случае, с Function Declaration, вы просто на каждой итерации цикла заново объявляете функцию example. Во втором же случае вы каждый раз заново определяете (переопределяете) переменную f. И в обоих случаях в массив записывается та функция, которая только что была объявлена.
Именно поэтому каждый раз это разная функция, а не ссылка на одну и ту же функцию (как вы можете видеть из моих примеров - ни одна функция не равно другой).
Здравствуйте,помогите разобраться почему Function Declaration объявленная в цикле,создается на каждой итерации.
Встречный вопрос: а какого поведения вы могли ожидать?
Воспроизведите этот код:
function example() {
return 1;
}
function example() {
return 2;
}
function example() {
return 3;
}
function example() {
return 4;
}
function example() {
return 5;
}
console.log(example());
В этом примере я реализовал то, что мог бы реализовать циклом, но сделал это вручную. Значение example равняется последней объявленной функции с этим именем. Проще говоря, example просто перезаписывается.
Абсолютно то же самое происходит и внутри цикла. На первой итерации вы определили функцию и добавили ее в массив. На второй итерации вы переопределили ранее определенную функцию и добавили уже переопределенную функцию в массив. И так далее.
Что касается этой части:
Основное отличие между ними: функции, объявленные как Function Declaration, создаются интерпретатором до выполнения кода.
Тут, вероятно, речь идет про, так называемый, Variable Hoisting. Про него уже достаточно много сказано, но, чтобы ответ соответствовал ответу, приведу цитату из книги С. Стоянова, которая максимально точно отражает происходящее "под капотом" (перевод под оригиналом):
To avoid hoisting always use a function expression.
// antipattern
// for illustration only
// global functions
function foo() {
alert('global foo');
}
function bar() {
alert('global bar');
}
function hoistMe() {
console.log(typeof foo); // "function"
console.log(typeof bar); // "undefined"
foo(); // "local foo"
bar(); // TypeError: bar is not a function
// function declaration:
// variable 'foo' and its implementation both get hoisted
function foo() {
alert('local foo');
}
// function expression:
// only variable 'bar' gets hoisted
// not the implementation
var bar = function() {
alert('local bar');
};
}
hoistMe();
In this example you see that, just like with normal variables, the mere presence of foo and bar anywhere in the hoistMe() function moves them to the top, overwriting the global foo and bar.
Чтобы избежать хоистинга, всегда используйте функциональные выражения (Function Expressions)
// антипаттерн
// только для примера
// глобальные функции
function foo() {
alert('global foo');
}
function bar() {
alert('global bar');
}
function hoistMe() {
console.log(typeof foo); // "function"
console.log(typeof bar); // "undefined"
foo(); // "local foo"
bar(); // TypeError: bar is not a function
// function declaration:
// переменная 'foo' и ее реализация "хоистятся"
function foo() {
alert('local foo');
}
// function expression:
// только переменная 'bar' "хоистится",
// не ее реализация
var bar = function() {
alert('local bar');
};
}
hoistMe();
В этом примере вы можете видеть, что, также, как и с "обычными" переменными, только лишь наличие foo или bar где угодно внутри функции hoistMe() перемещает их вверх функции, перезаписывая [ранее определенные] глобальные foo и bar.
Походу, если функция объявляется в цикле, то она не создается интерпретатором до выполнения кода. Зато, так как функция в js - это переменная, то ей можно добавлять поле с ключом i, переопределять его в цикле и переопределять всю функцию. После выполнения цикла в ней будут хранится последние значения
var arr = [];
try {
example();
} catch (err) {
console.log("error: "+err)
}
for(var i = 0; i < 5; i++) {
function example(){console.log("func init #"+i)}
example.i = i;
arr.push(example);
}
console.log(example.i);
example();
Как развивать веб-проекты в 2026 году: технологии, контент E-E-A-T и факторы доверия
Современные инструменты для криптотрейдинга: как технологии помогают принимать решения
Апостиль в Лос-Анджелесе без лишних нервов и бумажной волокиты
Основные этапы разработки сайта для стоматологической клиники