JS: Function Form vs Operator
in JavaScript since ECMAScript 2015, many functional forms are added that does the same thing an operator does.
example:
Advantage of function form
Function form lets you manipulate expressions at run-time.
JavaScript has functional form of operator Array.of Reflect.construct Reflect.deleteProperty Reflect.get Reflect.has Reflect.set show a example where function form is useful but operator cannot do it.
(ai answer)
Operators aren’t first-class. The function forms fix that, and they also expose extra arguments (receiver, newTarget) that syntax can’t.
Array.of vs new Array / []
Array(3) is length 3 (holes). Array.of(3) is [3]. You can also pass it as a callback:
[1, 2, 3].map(Array.of); // [[1], [2], [3]] // no operator equivalent: you can’t pass `[` around
Reflect.construct vs new
new Ctor(...args) always sets new.target to Ctor. Reflect.construct lets you pick a different prototype / new.target:
function Base() { console.log(new.target.name); } class Extra {} Reflect.construct(Base, [], Extra); // logs "Extra" // obj instanceof Extra === true // `new Base()` cannot do this
Also: Reflect.construct(Ctor, argsArray) — no need to write new Ctor(...args).
Reflect.deleteProperty vs delete
Returns success (boolean). delete is an expression, not a function.
const frozen = Object.freeze({ a: 1 }); Reflect.deleteProperty(frozen, "a"); // false — failed // delete frozen.a; // still false, but you can’t pass `delete` to .every() ["a", "b"].every((k) => Reflect.deleteProperty(obj, k));
Needed inside a Proxy deleteProperty trap to forward the real operation.
Reflect.get / Reflect.set vs . / =
You can choose the receiver (this for getters/setters). Property syntax always uses the object you wrote.
const proto = { get x() { return this._x; }, set x(v) { this._x = v; }, }; const a = Object.create(proto); const b = {}; Reflect.set(proto, "x", 42, b); // setter runs with this === b Reflect.get(proto, "x", b); // 42 // a.x = 42 always uses `a` as this — you cannot retarget it
Same reason Proxy get/set traps take receiver and should call Reflect.get/set(..., receiver).
Reflect.has vs in
Same check, but callable:
["id", "name"].every((k) => Reflect.has(user, k)); // you cannot write `.every(in)` — `in` is not a value
Shared theme: pass as a callback, apply to a dynamic key list, return success, or supply receiver / new.target. Operators can’t do those.