Ответ 1
В первом случае объект функции создается только при вызове этой функции.
Нет, функции создаются независимо.
Обратите внимание, что вы также можете сделать это:
function foo() {
}
function bar() {
}
var Baz = {
foo: foo,
bar: bar
};
Или это:
var Baz = (function() {
function foo() {
}
function bar() {
}
return {
foo: foo,
bar: bar
};
})();
Основная цель размещения функций на Baz
в качестве свойств - сделать их доступными как "методы" на Baz
. Это может быть для удобства, для "пространства имен" и т.д. В вашей первой форме (и моей первой форме выше), если этот код находится в глобальной области видимости, foo
и bar
добавляются в глобальную область, которая может получить довольно многолюдно довольно быстро (особенно в браузерах). Во втором примере единственным глобальным символом является Baz
, потому что функции анонимны. В моем последнем примере выше единственный глобальный символ Baz
, но функции не анонимны, у них есть имена, которые могут показать вам отладчики и трассировки стека (что хорошо, подробнее здесь).
С точки зрения попытки оптимизации при создании функций, как это работает: когда выполнение входит в заданный контекст (глобальный контекст или контекст, связанный с вызовом функции), все это делается:
- Создан контекстный объект выполнения за кадром.
- Создается объект переменной за кадром для этого контекста выполнения.
- В случае контекста функции:
- Свойство добавляется к объекту переменной для
arguments
(массивная вещь, которую вы можете использовать для доступа к аргументам) - Свойство добавляется к объекту переменной для каждой из функций с именем arguments, со значением аргумента
- Если функция имеет имя, ее имя добавляется как свойство объекта переменной и имеет значение объекта функции.
- Свойство добавляется к объекту переменной для
- Свойства создаются в объекте переменной для каждой переменной, объявленной с помощью
var
в контексте выполнения; их значения первоначальноundefined
(независимо от того, имеет ли на немvar
инициализатор). - Каждое объявление функции в контексте обрабатывается. (Функциональные выражения еще не обработаны, больше о различиях ниже). Свойство объекта переменной для каждого имени функции создается и получает объект функции как его значение.
- Выполняется пошаговое выполнение кода.
- Как и все выражения, выражения функций оцениваются, когда они встречаются в пошаговом потоке. Операторы
-
var
, которые имеют инициализаторы (например,var a = 2;
), обрабатываются точно так же, как и операторы присваивания (a = 2;
); аспектvar
был сделан гораздо раньше. (var
часто неправильно понимается. Например, у нас был этот вопрос вчера.)
Вы заметите разницу выше между объявлениями функций и выражениями функций. Вы можете указать, что именно выглядит, если посмотреть, используете ли вы результат как правое значение — то есть вы присваиваете результат переменной, используя ее как правую часть определения свойства в объектном литерале или передавая ее в функцию. Если да, то это выражение функции. Если вы этого не сделали, это объявление функции.
Пример объявления функции:
function foo() {
}
Пример выражения функции:
var foo = function() {
};
Другой:
var Baz = {
foo: function() { }
};
(Строка foo
является объявлением свойства в объектном литерале, который использует выражение функции для значения.)
Пример выражения с именованной функцией:
var f = function foo() { // <== Don't do this (more below)
};
Именованные функциональные выражения должны быть действительными, но они плохо поддерживаются реализациями в дикой природе (особенно IE), и поэтому на данный момент их следует избегать. Подробнее здесь.