Question 27 / 31
Does grouping a member expression in parentheses change what this is?
Topic: this bindingDifficulty: Intermediate
Parentheses around a property reference don't strip it — this is still bound the same way as calling the property directly.
Solve it with the execution visualizerStep through every binding, function call, and console output below.Predict the output
Predict all four lines. foo and bar each end up holding the same function as person.greeting, called four different ways.
var name = "Window";
var person = {
name: "Person",
greeting: function () {
console.log(this.name);
}
};
function greeting() {
var foo = person.greeting;
foo();
person.greeting();
(person.greeting)();
(bar = person.greeting)();
}
greeting();Reveal the answer and explanation
Expected output
Window
Person
Person
WindowWhy this happens
foo() calls through a bare variable holding the function — that variable is not a property reference, so default binding applies and this is the global object (window), printing "Window".
person.greeting() is a genuine member expression call: the receiver read off the reference is person, so implicit binding applies and this.name reads "Person".
(person.greeting)() wraps the exact same member expression in parentheses. The grouping operator only changes evaluation order/precedence — it does not turn a property reference into a plain value the way an assignment or comma expression would — so the call site is unchanged and this still resolves to person, printing "Person" again.
(bar = person.greeting)() looks similar, but the outer expression is now an assignment, not a bare property reference. An assignment expression evaluates to its right-hand value — the function itself, stripped of any receiver — so the call site behaves exactly like foo(): default binding applies and this is window again, printing "Window".
What this question tests
- this-binding depends on the call site's reference, not on which variable happens to hold the function
- the grouping operator (...) never strips a property reference — only operators that produce a new value (assignment, comma, etc.) do
- copying a method into a plain variable (var foo = obj.method) always loses its receiver
Runtime assumptions
Assumes a classic sloppy-mode script, where a receiver-less call's this defaults to the global object.