Functions, scope and closures
Three main ways to write a function:
- Declaration:
function login(user) {...}— hoisted (callable before its definition) - Expression:
const login = function(user) {...} - Arrow:
const login = (user) => {...}— short syntax, no ownthis
Arrow functions are everywhere in test code: callbacks (items.map(i => i.name)), test blocks (test('...', async ({ page }) => {...})).
Default parameters are handy for test helpers: function createUser(role = 'customer') {...}.
Scope is where a variable is visible. let/const are block-scoped: a variable declared inside { } is invisible outside.
A closure is a function "remembering" variables from where it was created. Practical use: creating configured helpers.
In test code, closures underpin fixtures and factory functions — e.g. calling makeApiClient(baseUrl) returns a client that remembers baseUrl.
Prepare a short closure definition for interviews: "A closure is a function plus its lexical environment. The function keeps access to outer-scope variables even after that scope has finished."