Ответ 1
В чем разница между вызовами
myFoo = Foo(5)
иmyFoo = new Foo(5)
?
Нет разницы для этого кода, потому что он возвращает объект, а spec говорит:
- Пусть результат будет вызван внутренним свойством [[Call]] F, предоставив obj как значение
this
и предоставив список аргументов, переданных в [[Construct]] в качестве аргументов.- Если
Type(result)
-Object
, то верните результат.
Так как эта функция возвращает результат, являющийся объектом, его результат используется. Вы заметили бы разницу, если бы он не возвращал объект, или если он был отмечен this
, например, если вы переписали его как:
function Foo(x) {
if (!(this instanceof Foo)) { return new Foo(x); }
this.bar = function() { return x; };
}
// Now instanceof works.
alert((new Foo) instanceof Foo);
Что вообще делает
new
в JavaScript?
Оператор new
вызывает вызов функции с помощью this
, связанного с вновь созданным Object
, прототипом которого является свойство функции prototype
.
Для пользовательских функций
new f(a, b, c)
эквивалентно
// Create a new instance using f prototype.
var newInstance = Object.create(f.prototype), result;
// Call the function
result = f.call(newInstance, a, b, c),
// If the result is a non-null object, use it, otherwise use the new instance.
result && typeof result === 'object' ? result : newInstance
Обратите внимание, что спецификация языка фактически определяет функции с двумя операциями, [[Call]] и [[Construct]], поэтому есть некоторые угловые случаи, когда new
ведет себя странно.
Например, связанные и встроенные функции:
var g = f.call.bind(f);
должен определять функцию, которая при вызове просто вызывает f
, поэтому g
должен быть таким же, как f
во всех отношениях, но
new g()
производит
TypeError: function call() { [native code] } is not a constructor
потому что встроенная функция Function.prototype.call
поддерживает [[Call]], но не [[Construct]].
Function.prototype.bind
также ведет себя по-разному вокруг new
и регулярных вызовов. Значение this
всегда является обязательным значением thisValue при вызове, но является вновь созданным экземпляром, когда вы используете new
.