Reputation: 2534
I want to know how the new
operator work and not just learn how to use it.I looked in the ECMAScript 5 standard and find the algorithm describe how it work but am a little confused about the meanning of it.
The production
NewExpression : new NewExpression
is evaluated as follows:
- Let
ref
be the result of evaluating NewExpression.- Let
constructor
be GetValue(ref).- If
Type(constructor)
is notObject
, throw aTypeError
exception.- If
constructor
does not implement the[[Construct]]
internal method, throw aTypeError
exception.- Return the result of calling the
[[Construct]]
internal method onconstructor
, providing no arguments (that is, an empty list of arguments).
I try to understand the algorithm above using this example:
var f = function() {};
var h = new f();
Particularly I don't understand the first step and therefore cannot follow the other steps.
- Let
ref
be the result of evaluating NewExpression.
var h = new f();
~~~ ~~~~
| \_________ NewExpression
new operator
Does that mean ref
is the value of f()
? But It's undefined
.
3 . If
Type(constructor)
is notObject
, throw aTypeError
exception.
But the type of f
is function, will it throw a TypeError
exception?
5 . Return the result of calling the
[[Construct]]
internal method onconstructor
, providing no arguments (that is, an empty list of arguments).
[[Construct]]
internal property of function, What's the meaning of calling it on constructor
?
Upvotes: 1
Views: 372
Reputation: 816442
First we have to clarify what new NewExpression
and especially NewExpression
are. This can be found in Annex A. The most common situation where this rule applies is when you don't pass arguments to the constructor. I.e.
var obj = new F;
where F
refers to a function. So this is the rule that lets you omit the parenthesis.
In your example (var h = new f();
), you have parenthesis though, i.e. you are passing an empty list of arguments, so this algorithm does not apply. f()
is not NewExpression
.
Instead this algorithm applies: new MemberExpression Arguments
. It is evaluated in pretty much the same way and the algorithm can found in §11.2.2 as well, just after the algorithm you quoted.
With this in mind, lets go through that algorithm step by step:
1. Let
ref
be the result of evaluatingMemberExpression
.
In your example, MemberExpression
, is f
, i.e. it is a variable. The result of the evaluation is a special Reference object. It's not important here what exactly it is. Just know that it holds information about how to actually get the value from the variable.
So now ref
refers to that reference.
2. Let
constructor
beGetValue(ref)
.
This is were the value of the variable is actually retrieved and constructor
will refer to the function that f
refers to.
3. Let
argList
be the result of evaluatingArguments
, producing an internal list of argument values (11.2.4).
In your case, Arguments
is ()
and therefore it is an empty list.
4. If
Type(constructor)
is notObject
, throw aTypeError
exception.
It is important to know that functions are objects too! So this step will throw the error if primitive values are being used in the new
expression.
5. If
constructor
does not implement the[[Construct]]
internal method, throw aTypeError
exception.
All functions (and potentially other objects) implement an internal [[Construct]]
property which does the actual instantiation of the new object. If the object does not have such a property, it cannot be used as constructor. How it works for functions is defined in §13.2.2.
6. Return the result of calling the
[[Construct]]
internal method on constructor, providing the listargList
as the argument values.
This is were the actual construction happens. [[Construct]]
is itself function and is defined in §13.2.2. The method is the same of every function and is responsible for creating a new object, call the function on that new object and return it or whatever the function returns.
Here is an example of what it would look in JavaScript (partly pseudo-code):
[[Construct]] = function(F, argList) {
// Create new object that in inherits from F.prototype or Object.prototype
var proto = F.prototype;
var obj = Object.create(typeof proto === 'object' ? proto : Object.prototype);
// Call F with this set to obj and pass the argument list
var result = F.apply(obj, argList);
// If result is not an object, return the generated object
return typeof result === 'object' ? result : obj;
};
Upvotes: 3
Reputation: 152986
Let's go through this step by step
new window['foo' + 1 + 'bar']
-> new window.foo1bar
window
? Local variable or property of the global object?Function
is a constructor, but not every constructor is a Function
. This point makes sure that new
is only called on constructors.MemberExpression : new MemberExpression Arguments
for the case new foo(...)
Upvotes: 2