I\'m playing around with different ways to call a function that is an attribute of an Object in Javascript and looking at which type of calls set \'this\' to be the Object a
Referencing ECMA-262 (edition five) which is probably difficult to follow (emphasis added):
10.2.1.2 Object Environment Records
Object environment records can be configured to provide their binding object as an implicit this value for use in function calls. This capability is used to specify the behaviour of With Statement (12.10) induced bindings. The capability is controlled by a provideThis Boolean value that is associated with each object environment record. By default, the value of provideThis is false for any object environment record.
10.2.1.2.6 ImplicitThisValue()
Object Environment Records return undefined as their ImplicitThisValue unless their provideThis flag is true.
- Let envRec be the object environment record for which the method was invoked.
- If the provideThis flag of envRec is true, return the binding object for envRec.
- Otherwise, return undefined.
10.4.3 Entering Function Code
- If the function code is strict code, set the ThisBinding to thisArg.
- Else if thisArg is null or undefined, set the ThisBinding to the global object.
10.4.1.1 Initial Global Execution Context
The following steps are performed to initialize a global execution context for ECMAScript code C:
- Set the VariableEnvironment to the Global Environment.
- Set the LexicalEnvironment to the Global Environment.
- Set the ThisBinding to the global object.
10.4.2 Entering Eval Code
The following steps are performed when control enters the execution context for eval code:
- If there is no calling context or if the eval code is not being evaluated by a direct call (15.1.2.1.1) to the eval function then,
- Initialize the execution context as if it was a global execution context using the eval code as C as described in 10.4.1.1.
- Else,
- Set the ThisBinding to the same value as the ThisBinding of the calling execution context.
11.1.1 The this Keyword
The this keyword evaluates to the value of the ThisBinding of the current execution context.
11.2.3 Function Calls
The production CallExpression : MemberExpression Arguments is evaluated as follows:
- Let ref be the result of evaluating MemberExpression.
- Let func be GetValue(ref).
- Let argList be the result of evaluating Arguments, producing an internal list of argument values (see 11.2.4).
- If Type(func) is not Object, throw a TypeError exception.
- If IsCallable(func) is false, throw a TypeError exception.
- If Type(ref) is Reference, then
- If IsPropertyReference(ref) is true, then
- Let thisValue be GetBase(ref).
- Else, the base of ref is an Environment Record
- Let thisValue be the result of calling the ImplicitThisValue concrete method of GetBase(ref).
- Else, Type(ref) is not Reference.
- Let thisValue be undefined.
- Return the result of calling the [[Call]] internal method on func, providing thisValue as the this value and providing the list argList as the argument values.
12.10 The with Statement
- Let oldEnv be the running execution context’s LexicalEnvironment.
- Let newEnv be the result of calling NewObjectEnvironment passing obj and oldEnv as the arguments
- Set the provideThis flag of newEnv to true.
this is assigned to the global object if:
Function.prototype.apply (15.3.4.3).Function.prototype.call (15.3.4.4).Function.prototype.bind (15.3.4.5) (not in ECMA252-3).MemberExpression Arguments syntax, meaning:
foo(arguments) is equivalent to foo.call((function() { }()), arguments); iff foo is callable and if you're not in a with statement.foo.bar(arguments) is equivalent to foo.bar.call(foo, arguments), evaluating foo only once, iff foo.bar is callable.eval if it is being called directly.My question is, why does
f=foo.bar; f();and(f=foo.bar)();assign 'this' to be the Global Object
This is detailed under section 11.2.3, step 6.a.i (6.1.1 above); ref is the f expression in your case (not its value), and GetBase(ref).ImplicitThisValue() is undefined (as a variable has an object environmental record as its base with provideThis set to false if that variable does not come from with).