A catalogue template contains a quantity of three. A write starts from that template, reports success, and leaves the template unchanged. The new quantity appears on another record instead. This is possible because the object where property rules are sought and the receiver used by the write can be different objects.
The short answer is that Reflect.set accepts an optional receiver. The target starts the property-setting operation; the receiver is carried through the relevant lookup and can become the object whose own data property is created or updated, or the this value supplied to a discovered setter. The target's descriptor rules still matter. Supplying a different receiver is not permission to bypass a non-writable property.
This lesson uses ordinary catalogue records and finite controlled JavaScript examples. It separates descriptor selection, receiver identity, property creation, setter invocation and the operation's reported outcome. Proxy traps, typed-array indexed writes and other exotic objects need their own additional contracts; the central examples deliberately keep those complications outside the first trace.
This specialist guide belongs to the Websites root. It also connects to The Gold Standard of Education | Learning That Transfers into Life and the How X Works hub. The worked cases are original teaching examples; their numbers are stipulated so that the reasoning can be checked.
eduKateSG · Websites
Find your next learning step
Trace Reflect.set through the target’s descriptor lookup and the actual write receiver. Compare data creation, receiver restrictions, setters and reported outcomes.
ROUTE 2 · CHAPTERS 3–4
Follow the governing descriptor
Trace inheritance and the earlier non-writable gate.
ROUTE 3 · CHAPTERS 5–6
Inspect the receiver
Compare existing data fields and an accessor that is not invoked.
ROUTE 4 · CHAPTERS 7–10
Follow the selected branch
Observe setter identity, exceptions, extensibility and conversion.
Chapter contents
Locate both objects · Chapters 1–2
1. Draw the starting target and receiver separately
2. Recover the default receiver before comparing ordinary calls
Follow the governing descriptor · Chapters 3–4
3. Follow inherited descriptor lookup without moving the receiver
4. Respect a non-writable descriptor before inspecting the receiver
Inspect the receiver · Chapters 5–6
5. Inspect an existing receiver data property before updating it
6. Do not invoke a receiver accessor from the writable-data branch
Follow the selected branch · Chapters 7–10
7. Supply the receiver as this to a discovered setter
8. Keep setter return values separate from Reflect.set results
9. Check receiver extensibility only when creating a field
10. Separate primitive receivers, missing properties and key conversion
Transfer and verify · Chapters 11–12
CHAPTER 1 OF 12 · Locate both objects
1. Draw the starting target and receiver separately
Begin with a template object whose own quantity property contains three. Create an empty draft object. Both are ordinary objects with ordinary extensible state. A call to Reflect.set starts at the template, supplies quantity as the key, seven as the value and draft as the explicit receiver.
The template's quantity is an ordinary writable data property. That permits the operation to continue along its ordinary data-property path. The receiver is an object, has no own quantity property and can acquire one. The call creates quantity on draft and reports true. Template quantity remains three.
const template = { quantity: 3 };
const draft = {};
Reflect.set(template, "quantity", 7, draft); // true
template.quantity; // 3
draft.quantity; // 7
Object.hasOwn(draft, "quantity"); // true
The two objects need not be related by inheritance in this explicit example. Draft was not constructed with template as its prototype. The operation uses the receiver argument supplied by the caller. A diagram showing an invented prototype arrow between them would misdescribe the fixture even though the final values happened to look plausible.
Use a ledger with target identity, receiver identity, descriptor found, operation result and final own properties. The target row explains where the ordinary setting rules began. The receiver row explains where the permitted data write was directed. Do not combine them into one destination column before checking whether they are actually the same object.
For independent practice, change the draft's label, then repeat the quantity write. The unrelated label remains and the new quantity is added. Next use a different empty receiver while keeping the template. The two draft quantities can differ because they are separate objects receiving separate writes; the template is not a shared quantity cell automatically updated by every successful call.
For a catalogue feature, this distinction can support deliberate per-record values governed by a template's descriptors. It can also explain a bug in which a developer checks the template after writing and wrongly concludes that true was a false success report. Inspect the intended receiver before judging what the operation promised to change.
| Observation | Before | After |
|---|---|---|
| Template own quantity | 3 | 3 |
| Draft own quantity | Absent | 7 |
| Reflect.set result | Not yet called | true |
CHAPTER 2 OF 12 · Locate both objects
2. Recover the default receiver before comparing ordinary calls
When the receiver argument is omitted, Reflect.set uses the target as the receiver. In the opening ordinary writable-data fixture, that means a three-argument call updates the template itself. The four-argument version changes the relationship by supplying a separate draft object.
Compare fresh copies rather than run both calls on one already changed object without recording the sequence. In the default case, template quantity becomes seven. In the separate-receiver case, the template retains three and draft acquires seven. The same key and proposed value do not imply the same final object state when the receiver differs.
A fourth argument explicitly supplied as undefined is not the same as omitting it. The default is selected by argument presence, not by a rule treating every undefined receiver as absent. Under the ordinary data-property path, a non-object receiver cannot receive a created own property, so this explicit undefined case reports false.
const first = { quantity: 3 };
Reflect.set(first, "quantity", 7); // true
const second = { quantity: 3 };
Reflect.set(second, "quantity", 7, undefined); // false
This is useful because wrapper functions sometimes always forward four positions, even when the caller did not supply the fourth. If that wrapper turns omission into explicit undefined, it can change behaviour. The issue is not a hidden change in the template's descriptor; it is a changed argument contract.
For transfer, compare an omitted receiver, the target itself as explicit receiver, a fresh object receiver and explicit null. Predict the boolean and own-property effects under the same ordinary writable target descriptor. Keep null separate from an empty object even if both are used informally to mean no prior draft.
A practical wrapper should preserve the intended distinction. It can deliberately use a default receiver, deliberately forward an explicit receiver, or reject unsupported inputs under its own documented policy. What it should not do is claim faithful forwarding while silently changing argument presence. The small four-row ledger makes that difference easy to test before it becomes a larger catalogue update problem.
CHAPTER 3 OF 12 · Follow the governing descriptor
3. Follow inherited descriptor lookup without moving the receiver
The starting target may not own the requested property. For an ordinary object, setting can continue through its prototype chain to find the relevant property-setting behaviour. The receiver carried into that continuation remains the receiver supplied to the original operation; it does not automatically become each prototype visited.
Make base contain writable quantity three. Let template inherit from base, with no own quantity. Supply a separate draft as receiver. The operation reaches base's quantity descriptor, follows the permitted data path and creates draft's own quantity. Neither base nor template gains a changed own quantity through that controlled call.
The diagram now has a real prototype arrow from template to base, plus a separate receiver box for draft. Trace descriptor lookup along the prototype arrow, but draw the new own property inside draft. These are two different movements in the explanation: locating the governing descriptor and performing the permitted receiver definition.
For a changed condition, add a writable own quantity descriptor to template. Lookup now finds that own descriptor first. The receiver still receives the data update under the ordinary compatible conditions. Which descriptor was found changes, but the receiver identity does not change merely because lookup ended sooner.
Now place a non-writable quantity on base while leaving template without an own override. The inherited restriction can stop the write before draft's own-property creation. A fresh extensible draft does not override that earlier target-chain condition. The next chapter develops that refusal directly.
For independent work, use two prototype levels with distinct unrelated fields and mark only the level owning quantity. Predict the number of own quantity properties before and after the operation. Reading template.quantity may still obtain base's value through inheritance even though template has no own field. The existing own-presence lesson supplies a fuller route into that separate observation.
A practical diagnosis should name the first relevant descriptor found, not merely say the property exists somewhere. Its kind and restrictions govern the next branch. Keeping the unchanged receiver visible prevents the common mistake of expecting the discovered prototype to become the automatic storage destination for every permitted write.
CHAPTER 4 OF 12 · Follow the governing descriptor
4. Respect a non-writable descriptor before inspecting the receiver
A non-writable data descriptor found along the ordinary target path makes the setting operation report false. A separate receiver does not bypass that restriction merely because it is empty, extensible or already contains a writable field with the same name. The earlier descriptor gate still applies.
Create a template with a non-writable own quantity of three. Create draft with its own ordinary writable quantity of one. Attempt to set seven through the template with draft as receiver. The result is false, template retains three and draft retains one. The receiver's apparently permissive state is not enough to authorize the operation.
const template = {};
Object.defineProperty(template, "quantity", {
value: 3, writable: false, configurable: true
});
const draft = { quantity: 1 };
Reflect.set(template, "quantity", 7, draft); // false
// template.quantity is 3; draft.quantity is 1.
Making the property configurable does not make this assignment writable. Configurability concerns other property-definition possibilities under their contracts. It does not tell Reflect.set to redefine a non-writable data property in order to make the requested write succeed.
For transfer, move the same non-writable descriptor onto a prototype and remove template's own quantity. The inherited target path can still reach and apply that restriction. Then deliberately add an own writable descriptor to template under a separately permitted definition operation and repeat. That changes which descriptor is selected; it is not the receiver bypassing the previously selected descriptor.
The distinction is especially useful around frozen objects. Freezing an ordinary object makes its own data properties non-writable. The existing frozen-outer lesson uses ordinary writes to demonstrate that local boundary. This article extends the reasoning by asking whether a separate receiver changes the result; in the developed non-writable data branch, it does not.
A practical repair should therefore begin with the intended authority. If the template's restriction is deliberate, accept the refusal and use the authorized update route. If the descriptor is incorrect, change it only through the appropriate explicit definition policy. Randomly swapping receiver objects cannot fix a refusal that occurs before their own fields become relevant.
CHAPTER 5 OF 12 · Inspect the receiver
5. Inspect an existing receiver data property before updating it
After the target path supplies a writable data descriptor, the receiver's own descriptor becomes relevant. If the receiver already owns a writable data property under the same key, the ordinary path can update that property's value. It does not need to create a new own property or copy the target's entire descriptor.
Give template an ordinary writable quantity of three. Define draft quantity as writable but non-enumerable and non-configurable, with value one. Reflect.set with seven and draft as receiver can update its value while retaining those receiver attributes. The receiver's existing descriptor is not replaced with the template's ordinary enumerable configurable shape.
This is a useful check because the final numeric value alone cannot establish whether attributes survived. Inspect draft's descriptor before and after. Its value changes from one to seven, writable remains true, enumerable remains false and configurable remains false under this fixture.
Change only draft quantity's writable attribute to false in a fresh test. The earlier target gate still permits progress, but the receiver's own non-writable data property now makes the operation report false. The descriptor causing refusal belongs to the receiver rather than to the target path in this version.
For independent practice, build two refusal rows with identical final values: one has a non-writable target quantity and a writable receiver quantity; the other has a writable target quantity and a non-writable receiver quantity. Require the learner to name the first failed gate. A message saying write denied is correct but insufficient to explain which design condition needs attention.
A catalogue adapter should preserve receiver attributes intentionally. If a field is non-enumerable for a documented serialization policy, a successful value update should not casually be described as recreating an ordinary public field. The update and its visibility to later consumers are different observations.
For practical tests, assert the boolean, target value, receiver value and full relevant descriptor fields. That small matrix catches an implementation that writes to the correct object but inadvertently replaces the wrong metadata through a different definition operation. Similar final values do not make different property operations interchangeable.
CHAPTER 6 OF 12 · Inspect the receiver
6. Do not invoke a receiver accessor from the writable-data branch
A particularly useful changed condition is an accessor on the receiver while the target path supplies a writable data descriptor. Under the ordinary setting algorithm, encountering that receiver-own accessor causes false. It does not call the receiver's setter as a fallback from this data-property branch.
Create template with ordinary writable quantity three. Give draft an own setter named quantity that would increment a counter. Calling Reflect.set(template, quantity, seven, draft) reports false, and the setter counter stays zero. A developer expecting every setter on any involved object to run will predict the wrong event history.
let calls = 0;
const template = { quantity: 3 };
const draft = { set quantity(value) { calls++; } };
Reflect.set(template, "quantity", 7, draft); // false
calls; // 0
Now contrast this with starting the operation at draft itself. That different target supplies its own accessor descriptor, so its setter can be the behaviour selected by lookup. The receiver-accessor refusal and the discovered-setter invocation are not contradictory rules; they occur in different branches with different descriptor owners.
The existing object-copying lesson explains target setter invocation when copying through assignment-like operations. Here the explicit separate receiver creates the additional distinction. Reading that older lesson as a rule that any same-named setter encountered anywhere must execute would overextend its scoped examples.
For transfer, give draft both a setter counter and another ordinary field holding a visible label. Verify that the refused write does not increment the counter or alter the label. Then move the accessor to the target and repeat with the same draft as receiver. Predict the newly selected setter's this identity before examining any field it writes.
A useful diagnostic note says writable data descriptor found on template, receiver owns an accessor under the key, operation returns false before invoking that accessor. This is more actionable than calling the setter broken. It tells the maintainer why the intended method was never selected and which contract would need to change for a setter-based design.
CHAPTER 7 OF 12 · Follow the selected branch
7. Supply the receiver as this to a discovered setter
When the relevant target-chain descriptor is an accessor with a setter, the ordinary path calls that setter with the receiver as its this value and the proposed value as its argument. The setter's code then determines which effects actually happen. It need not store the proposed value under the original property name at all.
Use a template setter for quantity that writes an own received field on this. Supply an empty draft as the explicit receiver and seven as the proposed value. The call invokes the setter with draft as this. Draft receives the new received field, while template does not acquire that field through this controlled setter body.
const template = {
set quantity(value) { this.received = value; }
};
const draft = {};
Reflect.set(template, "quantity", 7, draft); // true
draft.received; // 7
Object.hasOwn(template, "received"); // false
There is no own quantity data field on draft in this fixture. The selected setter stored under another name. Reporting true does not require the language to manufacture an own data property named quantity afterwards. The accessor's implementation defines the accepted operation's effects under its own code.
For a changed-context test, let the setter record its receiver in an external log rather than write this.received. The operation can invoke it successfully while neither object gains a new own data field. That does not make the true result an assurance that quantity was stored somewhere invisibly; it reports the successful setter path.
A setter discovered on an inherited prototype can receive the same explicit draft receiver. The receiver is carried through lookup as developed earlier. It does not become the prototype merely because that prototype owns the setter. Record descriptor owner and invocation receiver on separate lines.
For independent practice, give two draft objects distinct labels and invoke the same template setter with each. Have the setter log this.label alongside the supplied value. The resulting log connects receiver identity to the selected behaviour without relying on field creation. Then omit the receiver in a fresh call and explain why the default target becomes this instead.
For a catalogue feature, this can support deliberate normalization or validation behaviour, but those are promises implemented by the setter author. Reflect.set does not invent validation because the property has an accessor descriptor. Inspect the actual code and final application state before claiming that a successful invocation accepted a valid record or updated the visible catalogue.
CHAPTER 8 OF 12 · Follow the selected branch
8. Keep setter return values separate from Reflect.set results
An ordinary setter's returned JavaScript value is not used as the success boolean of the setting operation. A setter returning false can still be invoked normally, after which the ordinary accessor path reports true. Treating that returned false as an automatic refusal would confuse the setter function's completion with the surrounding operation's specified result.
Create a setter that logs its argument and returns false. Reflect.set can report true while the log records the call. The false return did not skip invocation or become a negotiated rejection signal. If the application wants a validation API returning an acceptance result, an explicit method with a documented return contract may express that job more clearly.
A setter that throws is different. A thrown error interrupts the operation and propagates to the caller rather than being transformed universally into false. Reflect.set is not an exception-swallowing wrapper around arbitrary setter code. Successful invocation, ordinary refusal and exceptional completion must remain distinct outcomes.
Use a distinctive Error object and a marker recorded before the throw. A test should assert the exact error identity and retain the earlier marker. The error does not erase the fact that the setter began or undo a counter it already changed. Catching it later is error handling, not rollback.
For transfer, compare a setter returning false, one returning an object and one throwing after incrementing a counter. All three can execute their initial marker. The first two can give a normal true Reflect.set result in the ordinary fixture; the third gives no normal boolean result. The proposed quantity can be identical in every row.
A getter-only accessor provides another normal-refusal case. If lookup finds an accessor descriptor without a setter, the ordinary operation reports false. Its getter is not invoked to discover a replacement setter or to obtain a writable destination. Accessor read and accessor write are different operations.
For a practical catalogue adapter, define what result callers should interpret. If they need a validated quantity, a setter invocation marker is insufficient. Check the actual accepted state or use an explicit update method returning a meaningful application result. The language-level boolean cannot certify a wider workflow that the setter never promised to complete.
CHAPTER 9 OF 12 · Follow the selected branch
9. Check receiver extensibility only when creating a field
A writable-data path may need to create an own property on a receiver that currently lacks it. An ordinary non-extensible receiver cannot acquire that new property, so creation can fail. This does not mean every write involving a non-extensible receiver must fail under every branch.
Begin with a writable template quantity and an empty draft made non-extensible. The attempted receiver field creation reports false. Template retains its quantity, and draft still has no own quantity. The receiver's inability to acquire a property explains this refusal after the earlier target descriptor gate passed.
Now give draft an existing writable own quantity before preventing extensions. Updating that existing property can succeed under the developed compatible conditions. Preventing extensions restricts additions; it does not automatically make every existing writable property non-writable. The distinction is also visible in the frozen-object specialist's comparison of integrity levels.
A discovered setter introduces another possible effect. It may write only to an external log and require no new own receiver property. A non-extensible draft does not itself prevent that setter invocation. Conversely, a strict setter body that tries to add a forbidden receiver field can throw during its own execution. The selected branch and setter implementation both matter.
For a bounded exercise, prepare three fresh receivers: empty extensible, empty non-extensible, and non-extensible with an existing writable quantity. Apply the same writable-data template operation. Predict true with creation, false without creation, and true with update. Inspect own presence and the relevant descriptors instead of inferring creation from a displayed inherited value.
Then change the target descriptor to a setter that only logs. Predict the invocation independently from the earlier data-creation outcomes. A learner who memorized non-extensible means all writes fail will miss why this operation has not attempted an ordinary own-property addition on the receiver.
For a practical feature, choose whether a draft is allowed to acquire fields or only update a prepared schema. Non-extensibility can help express the latter boundary for ordinary objects, but its role should remain precise. It is not a complete validity check, a recursive immutability policy or a guarantee that arbitrary accessors cannot change external state.
CHAPTER 10 OF 12 · Follow the selected branch
10. Separate primitive receivers, missing properties and key conversion
The receiver can be supplied explicitly as a primitive, but the ordinary writable-data branch cannot create an own data property on that primitive receiver. It reports false after reaching the relevant branch. This differs from rejecting the initial target argument, which Reflect.set requires to be an object.
A discovered strict setter can receive a primitive this value through the accessor call path. Its behaviour depends on the function's own strictness and implementation. To avoid accidental boxing assumptions, use an explicitly strict ordinary function in a controlled test when observing that identity. Do not extrapolate the data-branch refusal into a universal claim that every primitive receiver prevents a setter call.
If no property is found anywhere along an ordinary target chain, the ordinary setting rules reach a default writable-data path. With an extensible object receiver lacking the property, a new own field can be created there. The target itself need not gain the property when the receiver is separate.
For a clean fixture, use a target with a null prototype and no properties. Supply an empty object receiver and a new key code. The receiver can acquire code, while the target remains empty. The absent descriptor did not mean the operation had no possible permitted destination.
The property key also has its own conversion stage. Reflect.set accepts a supplied key value that is converted to a property key under the operation's contract. A custom conversion can run or throw before the target's setting algorithm reaches the descriptor branches being studied. Keep such effects separate from setter effects when diagnosing an active key object.
For independent practice, compare an ordinary string key, a retained symbol key and a key object whose conversion records a marker before returning quantity. Use the same target and receiver only when their state is deliberately reset. An error during conversion should not be reported as a setter refusal, because the setter stage was never reached.
The practical habit is to name each boundary: validate target, obtain property key, select receiver, inspect the relevant target-chain descriptor, and perform the appropriate branch. A single phrase such as assignment failed loses the stage needed to choose a safe repair and to understand which earlier effects may already have happened.
CHAPTER 11 OF 12 · Transfer and verify
11. Transfer the mechanism to a changed archive draft
The archive keeps a base record with an inherited writable revision field. A review template inherits from that base and has no own revision. A separate draft already owns a non-enumerable writable revision. The requested operation starts at the review template and supplies the draft as receiver.
Predict that descriptor lookup can reach the base's writable revision, while the receiver's existing data field is updated. The base's value stays unchanged, the template still lacks its own revision and the draft retains the existing non-enumerable attribute. Reading only template.revision after the operation would inspect the wrong object's resulting state.
Change only the base descriptor to non-writable in a fresh fixture. The operation now reports false before the receiver's otherwise writable field can authorize the update. Next restore the base's writable state but make the receiver revision non-writable. The operation again reports false, now for a different descriptor gate.
Replace the base's data descriptor with a setter that records this.code and the supplied revision in an external history. The receiver becomes the setter's this value. Whether it already owns revision is not used through the earlier data-property update branch, because a different target-chain descriptor kind has been selected.
Finally make that setter throw after recording history. The caller receives the error, but the history marker remains. The attempted update is not a transaction that automatically removes its earlier external entry. An archive needing atomic application updates requires an explicit design for that stronger promise.
For independent work, write a four-row ledger showing descriptor owner, descriptor kind, receiver descriptor, normal result or error and final changed objects. Predict each row before running code. The changed fixture tests inheritance, metadata preservation, independent refusal gates and accessor effects rather than simply repeating the opening quantity example with a new label.
A practical archive message should follow the actual application state. A true setting result can mean a data field was updated or a setter completed normally. Neither result alone establishes that a server accepted the revision or that the displayed review has been refreshed. Those are later workflow observations and should be checked under the archive's real service contract.
A second archive test changes a value without changing the reference path. Give a target a non-writable data property whose value is already seven, and ask Reflect.set to write seven again. The ordinary setting refusal still follows the non-writable descriptor. Do not borrow a different property-definition operation's compatibility rules and predict success merely because the proposed value equals the stored value. The selected operation matters alongside the descriptor.
Now compare an explicit Reflect.set result with a strict assignment using the ordinary target as its receiver. The explicit operation can report false for the refusal, while strict assignment can throw after a failed internal setting result. These are different caller-facing responses around the underlying restriction. A test should name the expression used rather than describe all unsuccessful writes as identical exceptions.
Finally, wrap the operation in a fictional update function returning the proposed revision regardless of the boolean. That wrapper can return seven even when Reflect.set returned false and no field changed. The wrapper's returned value does not override the language operation's result or create a successful archive update. Preserve all three observations: proposed revision, setting outcome and final stored revision. This is a useful transfer check because a visually convincing returned number can conceal the refused write.
For practical recovery, keep those observations attached to the actual receiver identity and record version. If the caller retries through a different receiver or after a descriptor change, that is a new operation requiring a new state check. The earlier false result does not predict every future attempt, and a later true result should not erase the history of the first refusal.
| Target-chain kind | Receiver condition | Outcome |
|---|---|---|
| Writable data | Writable existing data | Update receiver value |
| Non-writable data | Writable existing data | false at target gate |
| Writable data | Non-writable own data | false at receiver gate |
| Setter | Separate object | Invoke with receiver as this |
CHAPTER 12 OF 12 · Transfer and verify
12. Verify the write path and explain the actual result
Begin the controlled matrix with an ordinary writable target and a separate empty receiver. Assert that Reflect.set reports true, the target value stays unchanged, and the receiver acquires an own field with the expected value. Compare omitted receiver, explicit target receiver and explicitly supplied undefined to preserve argument-presence meaning.
Add inherited writable and inherited non-writable descriptors. Record the first relevant descriptor found and preserve receiver identity through the prototype traversal. A receiver that looks permissive must not conceal a refusal caused by the earlier target-chain restriction. Assert own presence separately from an inherited read result.
For existing receiver fields, compare writable data, non-writable data and an accessor with a counted setter. Verify that the compatible writable field retains its metadata, that the non-writable field refuses the change, and that the receiver accessor is not invoked from the developed target-writable-data path.
For target accessors, assert this identity, supplied argument, normal true result despite a false setter return, getter-only refusal and exact thrown-error identity. Preserve a marker before the throw. Add receiver extensibility cases so new-property creation and existing-property update are not conflated under one read-only label.
Keep the examples ordinary and finite. The tests do not certify every Proxy trap, platform object or application update policy. If a real wrapper introduces active descriptors, exotic indexed semantics or custom forwarding, extend the trace with that object's actual contract. Do not silently borrow the ordinary result as a universal prediction.
For a learner's final explanation, require the target, receiver and selected descriptor to be named before the final value. A correct answer says why the operation followed a data or accessor branch, which object changed, which restrictions were encountered and whether the caller observed true, false or an exception. It should also state what that result does not establish about later service work.
The useful repair follows that explanation. Supply the intended receiver, preserve omission correctly in a wrapper, use a compatible prepared field or choose an explicit update API where application acceptance matters. Once lookup rules and receiver effects are separate, a successful write that leaves the template unchanged becomes understandable rather than evidence of an unreliable boolean.
Continue with connected lessons
Separating a Frozen Outer Object from Immutable Nested Records
Separating a Frozen Outer Object from Immutable Nested Records. Compare the existing local integrity boundary with the explicit separate receiver in this lesson.
Separating Target Setter Calls from Data Property Creation When Copying Objects
Separating Target Setter Calls from Data Property Creation When Copying Objects. Distinguish copying through assignment-like setter behaviour from data-property construction.
Separating Descriptor Preparation from Target Changes in Object.defineProperties
Separating Descriptor Preparation from Target Changes in Object.defineProperties. Follow explicit property definition rather than importing assignment rules into descriptor preparation.
Frequently asked questions
Does the target always receive the changed data value?
No. An explicit separate receiver can receive the permitted own-property creation or update while the starting target remains unchanged.
Is omitted receiver the same as explicit undefined?
No. Omission selects the target as default receiver. Explicit undefined remains the supplied receiver and can fail the ordinary data-write path.
Can a separate writable receiver bypass a non-writable target descriptor?
Not under the developed ordinary data-property path. The target-chain non-writable descriptor causes refusal first.
Does a receiver's own setter always run?
No. When the selected target descriptor is writable data, an own accessor on the receiver causes false under this ordinary path instead of invoking that setter.
Does a setter returning false make Reflect.set return false?
Not automatically. A normally completed ordinary setter call leads to true under the accessor path; its returned value is not used as the setting boolean.
Does Reflect.set convert every exception into false?
No. Setter or key-conversion errors can propagate. Earlier effects are not automatically rolled back when an exception occurs.
Authoritative sources and further reading
ECMAScript: Reflect.set. Target validation, property-key conversion and receiver selection.
ECMAScript: OrdinarySetWithOwnDescriptor. The normative data and accessor branches, including receiver-own descriptor checks.
Return to the Websites subject guide, The Gold Standard of Education, or the How X Works hub.