Output Questions: this & Prototype Chain

Predict the output โ€” implicit/explicit/new binding, arrow functions, prototype lookup, class inheritance, and the classic this-loss traps.

must hard โฑ 28 min thisprototypenewcallapplybindarrowclassinheritance
Mastery:
Why interviewers ask this
this binding is the most commonly misunderstood JS concept. These questions separate candidates who have memorized rules from those who can reason through execution.

The four this rules (highest to lowest priority):

  1. new โ€” this is the newly created object.
  2. Explicit โ€” call/apply/bind sets this explicitly.
  3. Implicit โ€” obj.method() โ†’ this is obj.
  4. Default โ€” bare function call โ†’ this is global/undefined (strict).

Arrow functions have no own this โ€” they inherit from the enclosing lexical scope.


Q1 โ€” implicit binding

Run it yourself
Edit and run. Output is captured from console.log. Async logs (setTimeout/Promise) appear in real execution order.
Console
 
Answer & why
"Hello, Alice"
"Hello, undefined"

obj.greet() โ€” implicit binding: this is obj. fn() โ€” the method is extracted into a plain variable, so when called as fn(), this is global (window) or undefined (strict). window.name is "" (empty string in browsers, undefined in Node strict).


Q2 โ€” call, apply, bind

Run it yourself
Edit and run. Output is captured from console.log. Async logs (setTimeout/Promise) appear in real execution order.
Console
 
Answer & why
"Hello, Bob!"
"Hi, Bob?"
"Hey, Bob."
  • call(thisArg, ...args) โ€” sets this and spreads args.
  • apply(thisArg, argsArray) โ€” same but args as array.
  • bind(thisArg, ...partialArgs) โ€” returns a new function with this permanently bound. The 'Hey' is partially applied; '.' is the remaining argument.

Q3 โ€” arrow function: no own this

Run it yourself
Edit and run. Output is captured from console.log. Async logs (setTimeout/Promise) appear in real execution order.
Console
 
Answer & why
42
undefined

regular() โ€” implicit binding: this is obj, so this.value is 42. arrow() โ€” arrow functions donโ€™t have their own this. They inherit this from where they were defined โ€” at the object literal level, which is the global scope. global.value is undefined.


Q4 โ€” this in nested functions

Run it yourself
Edit and run. Output is captured from console.log. Async logs (setTimeout/Promise) appear in real execution order.
Console
 
Answer & why
undefined
"Outer"

getNameFn() returns a plain function. When called as (), this is global โ†’ global.name is undefined. getNameArrow() returns an arrow function. Arrows inherit this from the enclosing scope โ€” which is getNameArrowโ€™s this, which is obj (called as obj.getNameArrow()). So this.name is "Outer".


Q5 โ€” new binding

Run it yourself
Edit and run. Output is captured from console.log. Async logs (setTimeout/Promise) appear in real execution order.
Console
 
Answer & why
"Hi, I am Alice"
"Hi, I am Bob"
false

new Person('Alice') creates a fresh object, sets this to it, runs the constructor, and returns it. Each instance has its own name AND its own sayHi function (because itโ€™s created inside the constructor โ€” this wastes memory). If sayHi were on Person.prototype, instances would share one copy.


Q6 โ€” prototype chain lookup

Run it yourself
Edit and run. Output is captured from console.log. Async logs (setTimeout/Promise) appear in real execution order.
Console
 
Answer & why
"Dog"
"Dog speaks"
true
false
true

name is an own property on a. speak is on Animal.prototype โ€” not own. When you access a.speak, JS walks the prototype chain: a โ†’ Animal.prototype (found!). hasOwnProperty returns false for prototype-inherited properties. a.__proto__ points to Animal.prototype.


Q7 โ€” class inheritance and super

Run it yourself
Edit and run. Output is captured from console.log. Async logs (setTimeout/Promise) appear in real execution order.
Console
 
Answer & why
"Rex makes a noise. Woof!"
true
true
true

Dog.speak() calls super.speak() which invokes Animal.prototype.speak with this still being the Dog instance (d). instanceof walks the prototype chain โ€” d is both a Dog and an Animal. Object.getPrototypeOf(Dog) (not the instance โ€” the class itself!) is Animal โ€” classes inherit static methods too.


Q8 โ€” this lost in callback

Run it yourself
Edit and run. Output is captured from console.log. Async logs (setTimeout/Promise) appear in real execution order.
Console
 
Answer & why
regular: undefined
arrow: Save

clickRegular โ€” the callback is a regular function. When setTimeout calls it, this is global/undefined. global.label is undefined. clickArrow โ€” arrow function captures this from clickArrowโ€™s scope (which is the Button instance), so this.label is 'Save'.


Q9 โ€” bind priority over implicit

Run it yourself
Edit and run. Output is captured from console.log. Async logs (setTimeout/Promise) appear in real execution order.
Console
 
Answer & why
"A"
"B"

obj1.greet() โ€” implicit binding โ†’ this is obj1. boundToObj2() โ€” explicit bind wins over implicit. Even though greet was originally accessed via obj1, bind(obj2) permanently sets this to obj2.


Q10 โ€” class static this

Run it yourself
Edit and run. Output is captured from console.log. Async logs (setTimeout/Promise) appear in real execution order.
Console
 
Answer & why
1
101
1
101

Static methods are called on the class itself โ€” this is the class (constructor function). Counter.increment() uses this = Counter, so Counter.count becomes 1. SpecialCounter.increment() โ€” even though increment is inherited from Counter, this is SpecialCounter, so SpecialCounter.count becomes 101. Each subclass has its own count.


Q11 โ€” prototype property vs own property

Run it yourself
Edit and run. Output is captured from console.log. Async logs (setTimeout/Promise) appear in real execution order.
Console
 
Answer & why
1
3
2

f.x โ€” own property 1 shadows Foo.prototype.x = 2. f.y โ€” not own, found on prototype: 3. After delete f.x removes the own property, the prototypeโ€™s x = 2 is revealed. delete only removes own properties.


Q12 โ€” Object.create and prototype

Run it yourself
Edit and run. Output is captured from console.log. Async logs (setTimeout/Promise) appear in real execution order.
Console
 
Answer & why
"Hello from World"
true
false
true

Object.create(proto) creates an object whose [[Prototype]] is proto. obj.greet() finds greet on the prototype; this is obj (implicit binding). greet is NOT an own property โ€” itโ€™s on the prototype. name IS an own property (set directly on obj).

The this resolution rules โ€” ranked
1. new โ†’ fresh object. 2. bind/call/apply โ†’ explicit. 3. obj.method() โ†’ obj. 4. bare fn() โ†’ global/undefined. Arrow functions skip all rules โ€” they inherit this lexically from where they were written, not called.

Likely follow-up questions
  • What are the four rules for determining this?
  • Why does this change when you extract a method?
  • How does this work inside an arrow function?
  • What does new do step by step?
  • What is the prototype of a class instance?

References