How Does Javascript Determine When To Give A Function Call A "this" Context?
Solution 1:
That's a tricky one and boils down to the inner workings of the ECMAScript standard. The definition of the grouping operator is:
The production PrimaryExpression : ( Expression ) is evaluated as follows:
- Return the result of evaluating Expression. This may be of type Reference.
With the added note:
This algorithm does not apply
GetValue
to the result of evaluating Expression. The principal motivation for this is so that operators such asdelete
andtypeof
may be applied to parenthesised expressions.
So this is the key: The result can be of type Reference. A Reference is an internal data type which consists of a base value and a referenced name.
For example evaluating the member expression foo.bar
, results in a Reference with base value foo
(the object) and the referenced name "bar"
(simply a string representation of the identifier).
GetValue(ref)
is the internal function which actually accesses the property of the object and returns the value of the property (the function object in this examples). Most operators call GetValue
on their operands do resolve these References, but not the grouping operator.
Looking at how CallExpressions are evaluated might also give an idea of how this
and References work. For example, one step is:
Let thisValue be the result of calling the ImplicitThisValue concrete method of GetBase(ref).
So, if you have a Reference value and try to call it, the value of this
will be set to the base value of the Reference (foo
in the above example).
Regarding my example (true && foo.bar)();
: The &&
operator calls GetValue()
on both of its operands, so the result of the grouping operator is not a Reference.
Solution 2:
Anything of the form foo.bar()
is calling the bar
method of the foo
object.
However in the case of var bar = foo.bar; bar();
, you are creating a reference to the method and then calling the method with no context - hence it is given the default global context.
You can (except in old IE) do this: var bar = foo.bar.bind(foo); bar();
to have the function use the foo
context.
Post a Comment for "How Does Javascript Determine When To Give A Function Call A "this" Context?"