AI InterviewSearch…Search problems, topics, or pages…Ctrl KGet started
Skip to content

03 Functions, scope and closures / Checkpoint

Checkpoint — Functions, scope and closures

24 min · +25 XP · 3 exercises · 12 questions

Exercises0/3
Quiz · 70% to clear12 q

This checkpoint covers the three ways to define a function and how they hoist, parameters with defaults, rest and spread, lexical scope and the scope chain, closures and their patterns and pitfalls, the five rules for this with call/apply/bind, and higher-order functions — composition, currying and the callback convention.

How it works. Twelve questions and three programs; 70% on the questions and every program accepted clears the module.

Before you start, make sure you can answer:

  • Why a function declaration can be called above its line and a const arrow cannot.
  • When a default parameter applies, and the difference between rest and spread.
  • What a closure captures (variables, not values) and why for (var …) callbacks all see the last value.
  • The five this rules in precedence order, and the three ways to fix a detached method.
  • What bind returns and why it cannot rebind an arrow.
  • How pipe and compose differ, and why ["1","2"].map(parseInt) fails.

The programs are a counter factory with private state and an audit log, a this-binding tracer that prints which rule decided each call, and a small function-pipeline interpreter built from pipe, curry and once.

Common questions

Why can a function declaration be called before its line but a const arrow cannot?

A function declaration is hoisted with its body, so it is callable anywhere in its scope. A const is hoisted uninitialised and stays in the temporal dead zone until its line runs, so calling the arrow earlier throws a ReferenceError.

What are the three ways to fix a detached method in JavaScript?

Wrap the call in an arrow, () => obj.method(), so the dot call is preserved; bind it with obj.method.bind(obj); or define the method as an arrow class field, whose this is always the instance.

What does bind return in JavaScript?

bind returns a new function with this, and optionally leading arguments, fixed permanently; calling bind again on that function cannot change its this. On an arrow function it has no effect on this, because arrows have none of their own.

JavaScript Functions Quiz: Closures, this and Scope Practice

Test your JavaScript functions knowledge with 12 questions and three programs on hoisting, default and rest parameters, closures, this, bind and currying.

  • Course: JavaScript study plan
  • Module: Functions, scope and closures
  • Kind: Checkpoint — cleared at 70%
  • Reading time: 24 min
  • Runtime: Node 16

Checkpoint — Functions, scope and closures is the checkpoint that closes the Functions, scope and closures module: a graded quiz and whole-program exercises, passed at 70%.

Instructions

This checkpoint covers the three ways to define a function and how they hoist, parameters with defaults, rest and spread, lexical scope and the scope chain, closures and their patterns and pitfalls, the five rules for this with call/apply/bind, and higher-order functions — composition, currying and the callback convention.

How it works. Twelve questions and three programs; 70% on the questions and every program accepted clears the module.

Before you start, make sure you can answer:

  • Why a function declaration can be called above its line and a const arrow cannot.
  • When a default parameter applies, and the difference between rest and spread.
  • What a closure captures (variables, not values) and why for (var …) callbacks all see the last value.
  • The five this rules in precedence order, and the three ways to fix a detached method.
  • What bind returns and why it cannot rebind an arrow.
  • How pipe and compose differ, and why ["1","2"].map(parseInt) fails.

The programs are a counter factory with private state and an audit log, a this-binding tracer that prints which rule decided each call, and a small function-pipeline interpreter built from pipe, curry and once.

Common questions

Why can a function declaration be called before its line but a const arrow cannot?

A function declaration is hoisted with its body, so it is callable anywhere in its scope. A const is hoisted uninitialised and stays in the temporal dead zone until its line runs, so calling the arrow earlier throws a ReferenceError.

What are the three ways to fix a detached method in JavaScript?

Wrap the call in an arrow, () => obj.method(), so the dot call is preserved; bind it with obj.method.bind(obj); or define the method as an arrow class field, whose this is always the instance.

What does bind return in JavaScript?

bind returns a new function with this, and optionally leading arguments, fixed permanently; calling bind again on that function cannot change its this. On an arrow function it has no effect on this, because arrows have none of their own.

Exercises

A counter with an audit log

Write makeCounter() with private value and history and methods inc(by), dec(by), undo() (reverts the last change, returning undid <entry> or nothing to undo), get() and log() (the history entries like +5 -2 space-joined, or (empty)). Read n commands inc <k>, dec <k>, undo, get (prints value=<v>), log (prints log=<entries>).

Example: 7 then inc 5, inc 2, get, undo, get, log, undo →

value=7
undid +2
value=5
log=+5
undid +5

Binding precedence

Read three names and make objects a, b, c with those names. With function who() { return this === undefined ? "undefined" : this.name; }, print four lines: bindTwice=<who.bind(a).bind(b)()> (the first bind wins), callOnBound=<who.bind(a).call(c)> (call cannot override), arrowIgnoresBind=<an arrow returning this.name, bound to a, then called> — at the top level of a CommonJS file this is module.exports, whose name is undefined — and newOverridesBind=<new (Named.bind(b))(c.name).name> where function Named(name) { this.name = name; }.

Example: 3 Ada Bo Cy →

bindTwice=Ada
callOnBound=Ada
arrowIgnoresBind=undefined
newOverridesBind=Cy

A pipeline interpreter

The first line names steps, each name or name:arg, from a registry of step factories: inc, double, add:k, mul:k, and tap (passes the value through and increments a closure-held counter). The second line holds numbers. Build each step by calling its factory with the argument, pipe them, apply the pipeline to every number printing <x> -> <result>, then print tapped=<how many times tap ran>.

Example: inc tap double add:3 tap / 1 2 3 →

1 -> 7
2 -> 9
3 -> 11
tapped=6

In this module: Functions, scope and closures

← Higher-order functions — composition, currying and callbacks · Object literals — properties, keys, iteration and JSON →