π¨ JavaScript Β· Topic 14 of 20
The this Keyword β JavaScript Questions with Answers
30 practice questions on The this Keyword, each with the correct answer and a clear explanation of why it is right. Read through them as revision notes, or take this topic as an interactive quiz to test yourself.
1 easy Β· 13 medium Β· 16 hard Β· Part of JavaScript: The language of the web - basics to advanced, 20 topics.
Medium questions (13)
Q1. medium
What determines the value of this in a regular function?
- A HOW the function is called (the call site), not where it was defined
- B Where the function was written
- C The function's name
- D It is always the global object
Answer: A β HOW the function is called (the call site), not where it was defined
this is bound at call time. The same function can have different this values depending on whether it is called as a method, standalone, with new, or via call/apply/bind.
thisBinding
Q4. medium
What is this in a plain function call in STRICT mode?
function f() { return this; }
f();
- A undefined
- B window
- C The function
- D null
Answer: A β undefined
Strict mode (and ES modules) leave this undefined for standalone calls, preventing accidental writes to the global object. In sloppy mode it would be window.
Strict modeDefault binding
Q8. medium
What does .call() do?
fn.call(obj, a, b)
function greet(greeting) { return `${greeting} ${this.name}`; }
console.log(greet.call({name: "Ana"}, "Hi")); // "Hi Ana"
- A Calls fn immediately with this set to obj and arguments listed individually
- B Returns a new bound function
- C Calls fn with an array of arguments
- D Nothing
Answer: A β Calls fn immediately with this set to obj and arguments listed individually
call invokes right away with an explicit this. apply is identical but takes an ARRAY of arguments; bind returns a new function instead of calling.
callapplybind
Q9. medium
What is the difference between call() and apply()?
fn.call(obj, 1, 2);
fn.apply(obj, [1, 2]);
fn(...[1, 2]); // modern equivalent
- A call takes arguments separately; apply takes them as an ARRAY
- B apply does not set this
- C call returns a function
- D They are identical
Answer: A β call takes arguments separately; apply takes them as an ARRAY
Mnemonic: Apply = Array, Call = Comma. Modern spread syntax has made apply largely unnecessary: fn(...args).
callapplySpread
Q10. medium
What does .bind() return?
const greet = user.greet.bind(user);
btn.addEventListener("click", greet); // this stays user
- A A NEW function permanently bound to the given this - it does not call it
- B The result of calling the function
- C undefined
- D The original function
Answer: A β A NEW function permanently bound to the given this - it does not call it
bind creates a copy with this locked in, useful for callbacks and event handlers. You must store or pass the returned function.
bindCallbacks
Q14. medium
What is this in an event handler added with addEventListener?
btn.addEventListener("click", function() { ... });
btn.addEventListener("click", function() {
this.classList.add("active"); // this = btn
});
- A The element the listener is attached to (btn)
- B window
- C The event object
- D undefined
Answer: A β The element the listener is attached to (btn)
DOM listeners call the handler with this set to the current target - the same as event.currentTarget. But an ARROW handler would inherit this from the outer scope instead.
EventsDOM
Q17. medium
What is the old 'const self = this' pattern for?
run() {
const self = this;
setTimeout(function() { console.log(self.name); }, 100);
}
- A Saving the outer this in a variable so nested regular functions can use it
- B Creating a copy of the object
- C Making this global
- D Deleting this
Answer: A β Saving the outer this in a variable so nested regular functions can use it
Before arrow functions, developers wrote 'var self = this' (or that/_this) to carry the context into callbacks. Arrows made this unnecessary.
Legacy patternsArrow functions
Q18. medium
What is this inside a class method?
- A The instance the method was called on
- B The class itself
- C window
- D undefined always
Answer: A β The instance the method was called on
Class methods behave like object methods: user.getName() sets this to user. But class bodies are strict mode, so a detached method call gives undefined rather than window.
ClassesMethods
Q20. medium
What is this at the TOP LEVEL of a browser script (non-module)?
- A window (the global object)
- B undefined
- C document
- D null
Answer: A β window (the global object)
In classic scripts top-level this is window. In ES MODULES it is undefined, and in Node.js CommonJS it is module.exports - three different answers worth knowing.
Global thisModules
Q23. medium
What is the output?
function f() { return this; }
console.log(f.call(null)); // strict mode
- A null - strict mode passes the given value through unchanged
- B window
- C undefined
- D TypeError
Answer: A β null - strict mode passes the given value through unchanged
In sloppy mode, null/undefined would be replaced by the global object ('boxing'). Strict mode keeps exactly what you pass.
callStrict mode
Q25. medium
What is the output?
const o = {
a: 1,
inner: { a: 2, get() { return this.a; } }
};
console.log(o.inner.get());
- A 2 - this is the object immediately before the dot (inner)
- B 1
- C undefined
- D Error
Answer: A β 2 - this is the object immediately before the dot (inner)
Only the LAST object in the chain matters for implicit binding. o.inner.get() binds this to inner, not o.
Implicit bindingNested objects
Q27. medium
Does this exist inside a standalone arrow function at module top level?
- A It resolves to the module's this, which is undefined in ES modules
- B It is always window
- C It throws
- D It is the function
Answer: A β It resolves to the module's this, which is undefined in ES modules
Arrows have no own this, so they look outward. At module top level that is undefined; in a classic script it would be window.
ModulesArrow functions
Q29. medium
When should you deliberately choose a REGULAR function over an arrow?
- A When you need a dynamic this - object methods, constructors, prototype methods, some DOM handlers
- B Never - arrows are always better
- C Only for long functions
- D Only at top level
Answer: A β When you need a dynamic this - object methods, constructors, prototype methods, some DOM handlers
Arrows are great for callbacks that should keep the outer this. Regular functions are correct where this must be determined by the caller.
Arrow vs regularBest practices
Hard questions (16)
Q3. hard
What is the output?
const user = { name: "Ana", greet() { return this.name; } };
const g = user.greet;
console.log(g());
const g = user.greet.bind(user);
console.log(g()); // "Ana"
- A undefined - the function LOST its binding when detached from the object
- B "Ana"
- C TypeError
- D null
Answer: A β undefined - the function LOST its binding when detached from the object
this depends on the call site: g() has no object before the dot, so this is undefined (strict) or window (sloppy). Fix with g.bind(user) or an arrow wrapper.
- This is why passing methods as callbacks often breaks.
Losing thisbind
Q5. hard
What is this inside an ARROW function?
- A Inherited from the surrounding (lexical) scope - arrows have no own this
- B Always the global object
- C Always undefined
- D The object that called it
Answer: A β Inherited from the surrounding (lexical) scope - arrows have no own this
Arrows capture this where they are DEFINED, permanently. That makes them ideal for callbacks inside methods, and unsuitable as object methods themselves.
Arrow functionsLexical this
Q6. hard
What is the output?
const user = {
name: "Ana",
greet: () => `Hi ${this.name}`
};
console.log(user.greet());
- A "Hi undefined" - the arrow's this is the outer scope, not user
- B "Hi Ana"
- C TypeError
- D "Hi null"
Answer: A β "Hi undefined" - the arrow's this is the outer scope, not user
The arrow captured this from module/global scope where there is no name. Use shorthand method syntax: greet() { return `Hi ${this.name}`; }
Arrow functionsCommon mistakes
Q7. hard
Why does this arrow function work correctly?
const timer = {
count: 0,
start() { setInterval(() => this.count++, 1000); }
};
// broken version:
setInterval(function() { this.count++; }, 1000); // this is not timer
- A The arrow inherits this from start(), where this is timer
- B setInterval binds this
- C It does not work
- D count is global
Answer: A β The arrow inherits this from start(), where this is timer
This is the canonical good use of arrows: a callback inside a method that must keep the object's this. A regular function callback would get undefined/window instead.
Arrow functionsCallbacks
Q11. hard
Can a bound function be re-bound?
const f = fn.bind(a);
f.call(b);
- A No - the first bind wins; call/apply cannot override it
- B Yes, call overrides it
- C It throws an error
- D Only with apply
Answer: A β No - the first bind wins; call/apply cannot override it
bind creates a permanently bound function. This makes bound callbacks predictable, but means you cannot reuse them with a different this.
bindHard binding
Q12. hard
What is this inside a constructor called with new?
function User(name) { this.name = name; }
new User("Ana");
- A The brand-new empty object being created, which is returned automatically
- B The global object
- C undefined
- D The User function
Answer: A β The brand-new empty object being created, which is returned automatically
new creates an object, sets this to it, runs the function, and returns the object. This 'new binding' takes precedence over default and implicit binding.
newConstructors
Q13. hard
What is the precedence order of this binding rules?
- A new > explicit (bind/call/apply) > implicit (obj.method) > default (global/undefined)
- B default > implicit > explicit > new
- C They are all equal
- D Alphabetical
Answer: A β new > explicit (bind/call/apply) > implicit (obj.method) > default (global/undefined)
Check in that order to determine this. Arrow functions sit outside this system entirely - they simply inherit lexically.
Binding rulesPrecedence
Q15. hard
What is the output?
btn.addEventListener("click", () => console.log(this));
btn.addEventListener("click", (e) => {
e.currentTarget.classList.add("on"); // reliable
});
- A The surrounding scope's this (module/window) - NOT the button
- B The button
- C undefined always
- D The event
Answer: A β The surrounding scope's this (module/window) - NOT the button
Arrows ignore the DOM's this binding. If you need the element inside an arrow handler, use event.currentTarget instead.
Arrow functionsEvents
Q16. hard
What is the output?
const obj = {
name: "outer",
run() {
function inner() { return this?.name; }
return inner();
}
};
console.log(obj.run());
- A undefined - inner is a plain call, so it loses obj's this
- B "outer"
- C TypeError
- D null
Answer: A β undefined - inner is a plain call, so it loses obj's this
Nested regular functions do not inherit this. Classic fixes: make inner an arrow function, or capture 'const self = this' before it.
Nested functionsthis loss
Q19. hard
Why do React class components need this.handleClick = this.handleClick.bind(this)?
- A Because passing the method as a callback detaches it from the instance, losing this
- B React requires bind for all methods
- C To speed up rendering
- D It is optional decoration
Answer: A β Because passing the method as a callback detaches it from the instance, losing this
onClick={this.handleClick} passes the function alone. Without binding, this is undefined inside it. Modern alternative: define the handler as a class field arrow: handleClick = () => { }.
Reactbind
Q21. hard
What is the output?
const a = { name: "A", get() { return this.name; } };
const b = { name: "B" };
b.get = a.get;
console.log(b.get());
- A "B" - this follows the CALL SITE, not where the function was defined
- B "A"
- C undefined
- D TypeError
Answer: A β "B" - this follows the CALL SITE, not where the function was defined
The same function borrowed by another object gets that object's this. This 'method borrowing' is intentional and powers utilities like Array.prototype.slice.call(arguments).
Implicit bindingMethod borrowing
Q22. hard
What does Array.prototype.slice.call(arguments) do?
// modern equivalents:
Array.from(arguments);
[...arguments];
- A Borrows the array method to convert an array-LIKE object into a real array
- B Slices an array
- C Creates a new prototype
- D Nothing
Answer: A β Borrows the array method to convert an array-LIKE object into a real array
Before Array.from and spread, this was the standard way to arrayify arguments or NodeLists - by explicitly setting this to the array-like object.
callArray-like
Q24. hard
How do you make a method safe to pass as a callback?
class Btn {
handle = () => { console.log(this); }; // always bound
}
- A Bind it (obj.m.bind(obj)), wrap it in an arrow (() => obj.m()), or define it as a class-field arrow
- B Add the this keyword
- C Make it global
- D It cannot be done
Answer: A β Bind it (obj.m.bind(obj)), wrap it in an arrow (() => obj.m()), or define it as a class-field arrow
All three preserve the intended context. Class fields with arrows are popular because they bind once at construction with no extra code at the call site.
bindClass fields
Q26. hard
What is the output?
class A {
constructor() { this.v = 1; }
get() { return this.v; }
}
const a = new A();
const g = a.get;
console.log(g());
- A TypeError - class code is strict, so this is undefined and reading .v throws
- B 1
- C undefined
- D 0
Answer: A β TypeError - class code is strict, so this is undefined and reading .v throws
'Cannot read properties of undefined' - the classic detached-method error in classes. Bind it or use a class-field arrow.
ClassesStrict modebind
Q28. hard
What is the output?
const o = { name: "o" };
function f() { return this.name; }
console.log(f.bind(o).call({name: "x"}));
- A "o" - bind wins; call cannot override a bound function
- B "x"
- C undefined
- D TypeError
Answer: A β "o" - bind wins; call cannot override a bound function
Hard binding takes precedence over explicit call/apply. Only 'new' can override a bound this (and even then, only partially).
bindPrecedence
Q30. hard
What is globalThis?
- A A standard reference to the global object that works in browsers, Node and workers
- B The same as this in every context
- C A deprecated feature
- D The document object
Answer: A β A standard reference to the global object that works in browsers, Node and workers
Before globalThis you needed window (browser), global (Node) or self (workers). It gives one portable way to reach the global object.
globalThisEnvironments