Уже есть несколько очень хороших ответов, но я публикую новый, чтобы подчеркнуть мое наблюдение в случае III ниже о том, что происходит, когда у вас есть явный оператор возврата в функции, которую вы new
вызываете. Посмотрите на следующие случаи:
Случай I :
var Foo = function(){
this.A = 1;
this.B = 2;
};
console.log(Foo()); //prints undefined
console.log(window.A); //prints 1
Выше приведен простой пример вызова анонимной функции, на которую указывает Foo
. Когда вы вызываете эту функцию, она возвращается undefined
. Поскольку явного оператора возврата нет, интерпретатор JavaScript принудительно вставляет return undefined;
оператор в конец функции. Здесь окно является объектом вызова (контекстным this
), который получает новый A
иB
свойство.
Случай II :
var Foo = function(){
this.A = 1;
this.B = 2;
};
var bar = new Foo();
console.log(bar()); //illegal isn't pointing to a function but an object
console.log(bar.A); //prints 1
Здесь интерпретатор JavaScript, увидев new
ключевое слово, создает новый объект, который действует как объект вызова (контекстныйthis
) анонимной функции, на которую указывает указатель Foo
. В этом случае A
и B
становятся свойства вновь создаваемого объекта (вместо оконного объекта). Поскольку у вас нет явного оператора return, интерпретатор JavaScript принудительно вставляет оператор return, чтобы вернуть новый объект, созданный из-за использования new
ключевого слова.
Случай III :
var Foo = function(){
this.A = 1;
this.B = 2;
return {C:20,D:30};
};
var bar = new Foo();
console.log(bar.C);//prints 20
console.log(bar.A); //prints undefined. bar is not pointing to the object which got created due to new keyword.
Здесь снова интерпретатор JavaScript, увидев new
ключевое слово, создает новый объект, который действует как объект вызова (контекстуальный this
) анонимной функции, на которую указывает указатель Foo
. Снова,A
и B
становитесь свойствами вновь созданного объекта. Но на этот раз у вас есть явное выражение return, поэтому интерпретатор JavaScript не будет ничего делать самостоятельно.
В случае III следует отметить , что создаваемый объектnew
ключевого слова, был потерян с вашего радара. bar
на самом деле указывает на совершенно другой объект, который не тот, который интерпретатор JavaScript создал из-за new
ключевого слова.
Цитата Дэвида Фланагана из JavaScripit: Полное руководство (6-е издание), гл. 4, страница № 62:
Когда выражение создания объекта оценивается, JavaScript сначала создает новый пустой объект, такой же, как тот, который создан инициализатором объекта {}. Затем он вызывает указанную функцию с указанными аргументами, передавая новый объект в качестве значения ключевого слова this. Затем функция может использовать это для инициализации свойств вновь созданного объекта. Функции, написанные для использования в качестве конструкторов, не возвращают значение, а значением выражения создания объекта является вновь созданный и инициализированный объект. Если конструктор возвращает значение объекта, это значение становится значением выражения создания объекта, и вновь созданный объект отбрасывается.
--- Дополнительная информация ---
Функции, используемые во фрагменте кода вышеупомянутых случаев, имеют специальные имена в мире JS, как показано ниже:
Случай I и II - функция конструктора
Случай III - Заводская функция. Фабричные функции не должны использоваться с new
ключевым словом, которое я сделал, чтобы объяснить концепцию в текущем потоке.
Вы можете прочитать о разнице между ними в этой теме.