The four this rules (highest to lowest priority):
- new โ
thisis the newly created object. - Explicit โ
call/apply/bindsetsthisexplicitly. - Implicit โ
obj.method()โthisisobj. - Default โ bare function call โ
thisis global/undefined(strict).
Arrow functions have no own this โ they inherit from the enclosing lexical scope.
Q1 โ implicit binding
console.log. Async logs (setTimeout/Promise) appear in real execution order.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
console.log. Async logs (setTimeout/Promise) appear in real execution order.Answer & why
"Hello, Bob!"
"Hi, Bob?"
"Hey, Bob."call(thisArg, ...args)โ setsthisand spreads args.apply(thisArg, argsArray)โ same but args as array.bind(thisArg, ...partialArgs)โ returns a new function withthispermanently bound. The'Hey'is partially applied;'.'is the remaining argument.
Q3 โ arrow function: no own this
console.log. Async logs (setTimeout/Promise) appear in real execution order.Answer & why
42
undefinedregular() โ 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
console.log. Async logs (setTimeout/Promise) appear in real execution order.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
console.log. Async logs (setTimeout/Promise) appear in real execution order.Answer & why
"Hi, I am Alice"
"Hi, I am Bob"
falsenew 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
console.log. Async logs (setTimeout/Promise) appear in real execution order.Answer & why
"Dog"
"Dog speaks"
true
false
truename 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
console.log. Async logs (setTimeout/Promise) appear in real execution order.Answer & why
"Rex makes a noise. Woof!"
true
true
trueDog.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
console.log. Async logs (setTimeout/Promise) appear in real execution order.Answer & why
regular: undefined
arrow: SaveclickRegular โ 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
console.log. Async logs (setTimeout/Promise) appear in real execution order.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
console.log. Async logs (setTimeout/Promise) appear in real execution order.Answer & why
1
101
1
101Static 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
console.log. Async logs (setTimeout/Promise) appear in real execution order.Answer & why
1
3
2f.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
console.log. Async logs (setTimeout/Promise) appear in real execution order.Answer & why
"Hello from World"
true
false
trueObject.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).
this lexically from where they were written, not called.