Question presented to candidate: "Walk me through the exact rules JavaScript uses to decide what this refers to for a given function call, in priority order."
What a strong answer should cover:
- this is resolved by four concrete rules, checked in strict priority order, from highest to lowest: new binding, explicit binding (call/apply/bind), implicit binding (obj.method()), and default binding (a bare call).
- new binding: calling a function with new makes this the brand-new object being constructed, and this rule beats every other rule, including a prior .bind().
- Explicit binding: fn.call(obj), fn.apply(obj), and fn.bind(obj) all set this to the object you pass in -- and once a function is bound with bind, that binding is permanent and cannot be overridden by a later call or apply.
- Implicit binding: calling a function as obj.method() sets this to obj, the object immediately before the dot at the call-site -- not necessarily the object where the method was originally defined.
- Default binding: a bare function call (no object, no new, no explicit binding) sets this to undefined in strict mode, or the global object in sloppy (non-strict) mode.
- Arrow functions follow none of these four rules -- they have no this of their own and always inherit this lexically from their enclosing scope, unaffected by call, apply, or bind.
Clarifying questions expected:
- "Do you want me to cover how arrow functions interact with these rules too, since they are a deliberate exception?"
Code / implementation expected: Yes -- a runnable snippet exercising all four rules plus the arrow-function exception, with real observed this values for each.