In JavaScript, what is a template literal (a string written in backticks), and how does it differ from building the same string with the + operator?
answer
- Backticks, not quotes
- Any expression goes in the slot
- Newlines and indentation are literal
- Values pass through string conversion
- Symbols throw; objects give [object Object]
basics
~20 sA template literal is a backtick-delimited string that embeds any expression with ${...} and keeps newlines exactly as typed. Interpolated values are converted to strings automatically, so it produces what + would for most inputs, with far less quote juggling.
solid answer
~50 sA template literal is written in backticks instead of quotes. Inside it, `${ ... }` takes any *expression* — not just a variable — evaluates it, converts the result to a string, and splices it in. Newlines and leading indentation typed inside the backticks are part of the string, so multi-line text needs no `\n` and no concatenation. Single and double quotes need no escaping; a backtick, a backslash, or a literal `${` does. Against `+`, the everyday win is readability — you read the shape of the output instead of a chain of operands. The conversion is the ordinary one: an array becomes its comma-joined elements, a plain object becomes `[object Object]`, `null` becomes `"null"`. So interpolation is not a formatter and provides no escaping or safety of any kind. Templates also nest — a `${}` slot may hold another backtick string.
code
javascript · 11 linesconst user = { name: 'Ada', roles: ['admin', 'dev'] };
console.log(`${user.name} has ${user.roles.length} roles: ${user.roles}`);
// Ada has 2 roles: admin,dev
console.log(`object: ${user}`); // object: [object Object]
console.log(`missing: ${user.email}`); // missing: undefined
const indented = `first
second`;
console.log(JSON.stringify(indented)); // "first\n second"go deeper
Be able to write one from memory: backticks, ${expression}, real newlines, and no escaping needed for quotes. Say plainly that non-strings are converted to text automatically.
Explain the conversion rule concretely — arrays comma-join, plain objects become [object Object], null and undefined print as words, symbols throw — and note that indentation inside the literal is part of the value.
Show the production judgment: interpolation is not escaping, so templates that build markup or queries need a tagged form or a real escaping step, and whitespace-sensitive output needs deliberate dedenting.
Own the convention: where templates are the house string-building tool, decide which contexts must never use a bare template and provide the safe tagged helper, so correctness does not depend on each author remembering.
## The syntax A template literal is a string literal delimited by backticks (`` ` ``) instead of `'` or `"`. It arrived in ES2015 and adds two things ordinary string literals lack: **interpolation** and **literal newlines**. ```js const name = 'Ada'; const items = ['a', 'b']; const msg = `Hi ${name}, you have ${items.length} item(s).`; // 'Hi Ada, you have 2 item(s).' ``` Everything between `${` and its matching `}` is an **expression**, not merely a variable name. Function calls, ternaries, arithmetic, property access, even a nested template all work: ```js const n = 3; `You have ${n} ${n === 1 ? 'message' : 'messages'}${n > 0 ? ` (${n} unread)` : ''}`; ``` Evaluation is eager and left to right, top to bottom: every placeholder is evaluated once, at the moment the literal is evaluated, and the pieces are concatenated. There is no lazy or deferred behaviour — a template literal is an expression that produces a `string` and nothing more. ## Multi-line and whitespace A newline typed between backticks is a real newline in the value, and so is the indentation before it. This is the most common surprise: ```js function render() { return `line one line two`; } // 'line one\n line two' <- four spaces survive ``` Nothing dedents for you. If the surrounding code indentation must not leak into the output, either write the template flush against the left margin, strip it afterwards, or build it from an array and `join('\n')`. ## Escaping inside a template The usual backslash escapes still work (`\n`, `\t`, `\u{1F600}`). Three characters need escaping that quotes did not: a backtick (`` \` ``), a backslash (`\\`), and a literal dollar-brace sequence (`\${`) when you want the text `${` rather than a placeholder. Conversely, `'` and `"` are ordinary characters inside a template, which is why templates are pleasant for HTML-ish or quote-heavy text. ## The conversion rule Each interpolated value goes through the language's string conversion (the spec's ToString), the same operation `String(value)` performs. Practical consequences: - `` `${[1, 2]}` `` is `'1,2'` — arrays join with commas, and an empty slot or `null` element becomes empty text. - `` `${{ a: 1 }}` `` is `'[object Object]'` — a plain object's default `toString`. Interpolation never inspects an object's contents the way a debugger view does; reach for `JSON.stringify` when you want the shape. - `` `${null}` `` is `'null'` and `` `${undefined}` `` is `'undefined'` — both become visible text, which is why a missing field shows up as the word "undefined" in a rendered string. - A symbol throws: `` `${Symbol('id')}` `` raises a `TypeError`, because string conversion refuses symbols. `String(sym)` is the one conversion that is allowed to produce `'Symbol(id)'`. There is one narrow divergence from `+`: interpolation asks an object for a string first, while `+` asks it for its default primitive. An object that defines both `valueOf` and `toString` can therefore stringify differently in the two forms: ```js const weird = { valueOf: () => 1, toString: () => 'S' }; '' + weird; // '1' `${weird}`; // 'S' ``` For ordinary values — strings, numbers, booleans, arrays, plain objects — the two agree. ## What it deliberately does not do Interpolation performs **no escaping**. A template literal that builds markup, a shell command, or a query splices attacker-controlled text in verbatim; the backticks add nothing defensive. The language's answer to that is the tagged form, where a function receives the static chunks and the values separately and can transform the values. A plain template literal is pure convenience. It also does not format: no padding, no locale-aware numbers or dates, no precision control. Those come from methods on the value or from the `Intl` APIs, applied inside the placeholder. ## When to prefer which Use a template literal for anything with more than one moving part, for multi-line text, and for strings full of quotes. Plain `+` still reads fine for a single concatenation (`prefix + id`). Performance is not a deciding factor: engines compile both to comparable work, so choose on readability. One genuine caveat is that a long multi-line template inside indented code carries that indentation, so templates used for whitespace-sensitive output (YAML, Python-like text, some Markdown) need care.
- What does a template literal do with an object that has no custom toString?It produces `'[object Object]'`, the default `Object.prototype.toString` result — interpolation converts to a string, it does not inspect structure. If you want the contents, call `JSON.stringify(obj)` inside the placeholder, and remember that stringify drops functions and `undefined` properties.
- Is there any value that a template literal refuses to interpolate?Yes — a symbol. `` `${Symbol('id')}` `` throws a `TypeError`, because the language's string conversion rejects symbols to stop them leaking into text accidentally. The explicit `String(sym)` call is special-cased and returns `'Symbol(id)'`, so wrap the symbol if you actually want it printed.
- How do you write a template that must contain the literal characters ${ without starting a placeholder?Escape the dollar sign: `` `costs \${amount}` `` yields the text `costs ${amount}`. Backticks and backslashes need the same treatment inside a template (`` \` `` and `\\`), while single and double quotes are ordinary characters and need none.
saying these in an interview costs you the question
- Says only variables, not expressions, fit inside ${}
- Thinks leading indentation in a multi-line template is stripped
- Believes template literals escape HTML or make strings safe
- Expects ${obj} to print the object's properties
- Claims template literals are slower so should be avoided