As far as I understand, in JavaScript (Gecko variant) this:
var a = new A();
is a syntactic sugar for something like this:
var a = {};
a.__proto__ = A.prototype;
A.call(a);
Because of that, A() (which is equivalent to A.call()?) and new A() should produce two different results, like these:
>>> new Date()
Fri Nov 19 2010 01:44:22 GMT+0100 (CET) {}
>>> typeof new Date()
"object"
>>> Date()
"Fri Nov 19 2010 01:44:42 GMT+0100 (CET)"
>>> typeof Date()
"string"
So far so good.
But, core object Function
behaves differently:
>>> Function('return 123;')
anonymous()
>>> typeof Function('return 123;')
"function"
>>> Function('return 123;')()
123
>>> new Function('return 123;')
anonymous()
>>> typeof new Function('return 123;')
"function"
>>> new Function('return 123;')()
123
Am I missing some trivial thing here ?
JavaScript at a language level doesn't specify a particular ‘standard’ way of using constructors. When you define your own constructor function, you can choose to have it callable as a constructor (with new
), as a function (returning a new object), or make it work with either.
Am I missing some trivial thing here?
Not really. The Function
constructor function is defined to be usable as a constructor even without new
, by ECMAScript section 15.3.1:
When
Function
is called as a function rather than as a constructor, it creates and initialises anew Function
object. Thus the function callFunction(...)
is equivalent to the object creation expressionnew Function(...)
with the same arguments.
The Date
function, on the other hand, is defined (by ECMAScript section 15.9.2) to return a string:
When Date is called as a function rather than as a constructor, it returns a String representing the current time (UTC).
NOTE: The function call
Date(...)
is not equivalent to the object creation expression new Date(...) with the same arguments.
The NOTE is there because so many constructor functions can also be used without new
. That's not because of any over-arching thinking that all constructor functions should be allowed to work as plain functions, but because this is just what JavaScript has always done since the early Netscape days. Netscape couldn't think of anything special for Function()
to do, so it just reproduced the new
functionality. They didn't pay too much attention to making the language consistent.
You wouldn't design a language's default class library like that if you were sane. But JavaScript isn't a sane language. It's a quick hack that got way out of hand, achieving mass popularity way before anyone spent any time refining its design. Expect it to behave consistently and you will only be disappointed.
The Function
constructor called as a function is just equivalent as using it in an expression with the new
operator, the case is described in the specification.
From § 15.3.1: The Function Constructor Called as a Function
...
Thus the function call Function(...) is equivalent to the object creation expression new Function(...) with the same arguments.
There are other built-in constructors that behave just like this, for example, the Array constructor called as a function:
Array(1,2,3); // [1,2,3]
new Array(1,2,3); // [1,2,3]
Other constructors like the ones that create primitive value wrappers (Boolean
, String
, Number
and Date
) behave differently.
The first three if you use call them without the new
operator, they just perform type conversion, for example:
typeof Number("20"); // "number"
typeof String(0xFF); // "string"
typeof String({toString: function () { return 'foo' }}); // "string"
typeof Boolean(""); // "boolean"
typeof Boolean(0); // "boolean"
While if you use them with the new
operator, they will return wrapper objects:
typeof new Number(20); // "object"
typeof new String('foo'); // "object"
typeof new Boolean(true); // "object"
This kind of objects are called primitive wrappers, they have an internal property named [[PrimitiveValue]]
where they store their underlying value (more on Objects vs Primitives).
Objects created with the Date
constructor are also primitive wrappers their underlying value is a numeric representation of the time value.
The semantics of the Date
constructor are also fully described, if it's called as a function, it will return a "string representing the current time (UTC)".
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With