πŸŽ“ Velnov

🟨 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.

Key concepts in this topic

thisBindingMethodsImplicit bindingLosing thisbindStrict modeDefault bindingArrow functionsLexical thisCommon mistakesCallbackscallapplySpreadHard bindingnewConstructorsBinding rulesPrecedenceEventsDOMNested functionsthis loss

Jump to: Easy Β· Medium Β· Hard

Easy questions (1)

Q2. easy

What is this inside an object method? const user = { name: "Ana", greet() { return this.name; } }; user.greet();

  1. A The object before the dot - user, so it returns "Ana"
  2. B The global object
  3. C undefined
  4. D The function itself

Answer: A β€” The object before the dot - user, so it returns "Ana"

In a method call obj.method(), this is obj. This 'implicit binding' is the most common case.

MethodsImplicit binding

Medium questions (13)

Q1. medium

What determines the value of this in a regular function?

  1. A HOW the function is called (the call site), not where it was defined
  2. B Where the function was written
  3. C The function's name
  4. 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();

  1. A undefined
  2. B window
  3. C The function
  4. 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"
  1. A Calls fn immediately with this set to obj and arguments listed individually
  2. B Returns a new bound function
  3. C Calls fn with an array of arguments
  4. 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
  1. A call takes arguments separately; apply takes them as an ARRAY
  2. B apply does not set this
  3. C call returns a function
  4. 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
  1. A A NEW function permanently bound to the given this - it does not call it
  2. B The result of calling the function
  3. C undefined
  4. 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
});
  1. A The element the listener is attached to (btn)
  2. B window
  3. C The event object
  4. 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);
}
  1. A Saving the outer this in a variable so nested regular functions can use it
  2. B Creating a copy of the object
  3. C Making this global
  4. 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?

  1. A The instance the method was called on
  2. B The class itself
  3. C window
  4. 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)?

  1. A window (the global object)
  2. B undefined
  3. C document
  4. 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

  1. A null - strict mode passes the given value through unchanged
  2. B window
  3. C undefined
  4. 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());

  1. A 2 - this is the object immediately before the dot (inner)
  2. B 1
  3. C undefined
  4. 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?

  1. A It resolves to the module's this, which is undefined in ES modules
  2. B It is always window
  3. C It throws
  4. 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?

  1. A When you need a dynamic this - object methods, constructors, prototype methods, some DOM handlers
  2. B Never - arrows are always better
  3. C Only for long functions
  4. 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"
  1. A undefined - the function LOST its binding when detached from the object
  2. B "Ana"
  3. C TypeError
  4. 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?

  1. A Inherited from the surrounding (lexical) scope - arrows have no own this
  2. B Always the global object
  3. C Always undefined
  4. 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());

  1. A "Hi undefined" - the arrow's this is the outer scope, not user
  2. B "Hi Ana"
  3. C TypeError
  4. 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
  1. A The arrow inherits this from start(), where this is timer
  2. B setInterval binds this
  3. C It does not work
  4. 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);

  1. A No - the first bind wins; call/apply cannot override it
  2. B Yes, call overrides it
  3. C It throws an error
  4. 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");

  1. A The brand-new empty object being created, which is returned automatically
  2. B The global object
  3. C undefined
  4. 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?

  1. A new > explicit (bind/call/apply) > implicit (obj.method) > default (global/undefined)
  2. B default > implicit > explicit > new
  3. C They are all equal
  4. 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
});
  1. A The surrounding scope's this (module/window) - NOT the button
  2. B The button
  3. C undefined always
  4. 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());

  1. A undefined - inner is a plain call, so it loses obj's this
  2. B "outer"
  3. C TypeError
  4. 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)?

  1. A Because passing the method as a callback detaches it from the instance, losing this
  2. B React requires bind for all methods
  3. C To speed up rendering
  4. 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());

  1. A "B" - this follows the CALL SITE, not where the function was defined
  2. B "A"
  3. C undefined
  4. 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];
  1. A Borrows the array method to convert an array-LIKE object into a real array
  2. B Slices an array
  3. C Creates a new prototype
  4. 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
}
  1. A Bind it (obj.m.bind(obj)), wrap it in an arrow (() => obj.m()), or define it as a class-field arrow
  2. B Add the this keyword
  3. C Make it global
  4. 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());

  1. A TypeError - class code is strict, so this is undefined and reading .v throws
  2. B 1
  3. C undefined
  4. 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"}));

  1. A "o" - bind wins; call cannot override a bound function
  2. B "x"
  3. C undefined
  4. 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?

  1. A A standard reference to the global object that works in browsers, Node and workers
  2. B The same as this in every context
  3. C A deprecated feature
  4. 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

Practice β€œThe this Keyword” as a quiz