The asterisk in JavaScript

* multiplies and ** raises to a power, so 2 ** 10 is 1024. function* declares a generator, a function that can pause and hand back values one at a time, and yield* passes control to another iterable. If you came from Python looking for *args, JavaScript uses three dots instead: ...args.

Every * in JavaScript

You write It means
a * b, a *= b Multiply
a ** b, a **= b Exponentiation (ES2016 and later)
function* gen() {} A generator function
*gen() {} inside a class or object A generator method
async function* gen() {} An async generator, for for await...of
yield* iterable Yield every value from another iterable
import * as ns from "mod" Import the whole module as one object
export * from "mod" Re-export everything a module exports
/* ... */ A comment
/a*/ A regex: zero or more a

Generators: function*

A generator runs until it hits yield, hands that value out, and waits until something asks for the next one:

function* countdown(n) {
  while (n > 0) yield n--;
}

console.log([...countdown(3)]);   // [ 3, 2, 1 ]

const it = countdown(2);
console.log(it.next());   // { value: 2, done: false }
console.log(it.next());   // { value: 1, done: false }
console.log(it.next());   // { value: undefined, done: true }

The * can sit against function or against the name. function* countdown and function *countdown are identical, and Prettier formats both as function*. There's no generator form of an arrow function, so *() => {} is a syntax error.

yield*: handing off to another iterable

yield* yields every value from whatever iterable follows it: another generator, an array, a string, a Set or a Map.

function* letters() {
  yield "a";
  yield "b";
}

function* everything() {
  yield* letters();
  yield* [1, 2];
  yield* "hi";
}

console.log([...everything()]);   // [ 'a', 'b', 1, 2, 'h', 'i' ]

Without the *, yield letters() would hand out the generator object itself as a single value. That's the most common generator bug.

** and the minus-sign rule

** is right-associative, like in math: 2 ** 3 ** 2 is 2 ** 9, which is 512. It works on BigInt too: 2n ** 64n is 18446744073709551616n.

Unlike Python, JavaScript refuses to guess what -2 ** 2 means:

-2 ** 2;     // SyntaxError: Unary operator used immediately before exponentiation expression
(-2) ** 2;   // 4
-(2 ** 2);   // -4

Math.pow(a, b) gives the same result as a ** b for ordinary numbers, but it doesn't accept BigInt.

Spread and rest are dots, not asterisks

Python unpacks with * and **. JavaScript does the same jobs with ...:

Python JavaScript
def f(*args): function f(...args) {}
f(*items) f(...items)
[*a, *b] [...a, ...b]
{**a, **b} { ...a, ...b }
first, *rest = items const [first, ...rest] = items;
def f(**kwargs): function f(options) {}, then destructure: const { size, ...others } = options;

JavaScript has no separate keyword arguments, so the usual stand-in for **kwargs is a single options object.

import * as

import * as path from "node:path" gives you one object holding everything the module exports, so you call path.join(). Bundlers can still drop the exports you never touch, but only when the code accesses them as plain properties like path.join. Passing the whole namespace object around stops that from working.