A bound JavaScript function can keep a chosen receiver during an ordinary call and still ignore that receiver when used with new. The apparent contradiction disappears when we separate two operations. Calling a bound function forwards its stored receiver and prepends its stored arguments. Constructing through a bound function forwards construction to its target; the stored arguments remain, while the stored receiver does not become the new instance.
The short answer is to trace the operation first, then the receiver, argument order and result. Binding does not make every function a constructor, does not clone an object, and does not give an arrow function a new lexical this. The examples below use original, small records so that each change can be checked. They concern ordinary JavaScript behaviour in a modern runtime, not the separate lifecycle rules of an event system or framework.
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 operation, receiver, leading arguments and result separately. Construction retains the argument prefix without using the stored receiver as the instance.
ROUTE 1 · CHAPTERS 1–3
Trace ordinary calls
Identify the wrapper and follow arguments and stored receiver.
ROUTE 2 · CHAPTERS 4–6
Change preparation and operation
Rebind, mutate settings and compare call with construction.
ROUTE 3 · CHAPTERS 7–9
Check capabilities and identity
Distinguish arrows, classes and ordinary instance prototypes.
ROUTE 4 · CHAPTERS 10–12
Follow constructor outcomes
Trace explicit returns, new.target and a controlled ledger.
Chapter contents
Trace ordinary calls · Chapters 1–3
1. Keep the target, receiver and wrapper in separate boxes
2. Trace leading arguments before later arguments
3. A later call cannot replace the stored ordinary-call receiver
Change preparation and operation · Chapters 4–6
4. Rebinding adds a layer without replacing the first receiver
Check capabilities and identity · Chapters 7–9
7. Construction depends on the target being constructable
8. Arrow functions retain their lexical this
9. Trace instance prototypes separately from the bound receiver
Follow constructor outcomes · Chapters 10–12
10. An explicit object return still matters
Use and verify · Chapters 13–14
13. Keep preparation distinct from application lifecycle
14. Finish with an explanation that survives one changed input
CHAPTER 1 OF 14 · Trace ordinary calls
1. Keep the target, receiver and wrapper in separate boxes
Start with three things that are easy to collapse into one. The target is the function whose body will eventually run. The receiver is the value intended for its this during an ordinary call. The bound function is a new function object that stores the target, a receiver and any leading arguments. Calling bind creates that wrapper; it does not execute the target body merely because a receiver was supplied.
Use a strict ordinary function that returns a label. Our receiver has a prefix property, and the function accepts a category followed by a name. Binding fixes the receiver and the first argument. The later call supplies the remaining name. Reading the code from left to right is useful, but the essential operation is joining the stored argument list to the later argument list before the target is called.
function label(category, name) {
"use strict";
return `${this.prefix}:${category}:${name}`;
}
const desk = { prefix: "North" };
const labelBook = label.bind(desk, "book");
labelBook("Atlas"); // "North:book:Atlas"
The result contains North because the target reads this.prefix from desk. It contains book because that is the stored leading argument. Atlas comes from the eventual call. None of those facts means that labelBook is a method stored on desk. It is a separate value that can be passed or saved elsewhere while retaining its stored ordinary-call receiver.
For a first evidence check, count target executions. If the target increments a counter, creating labelBook leaves the counter unchanged; calling labelBook increments it once. This distinguishes preparation from execution. It also prevents a common debugging mistake: blaming the binding line for an effect that actually occurs much later when another part of the program invokes the wrapper. Keep creation time and call time as separate events in the trace.
CHAPTER 2 OF 14 · Trace ordinary calls
2. Trace leading arguments before later arguments
A bound argument is not a default that waits to see whether the caller supplies something better. It is an argument already placed at the front of the eventual list. If the caller supplies another category-looking string, that string occupies the next position; it does not replace the stored category. Parameter names do not travel with argument values to negotiate where each value belongs.
Imagine a target that returns all the arguments it receives. Bind the first two values, red and small, then call with blue and large. The target receives red, small, blue, large in that order. This is a useful diagnostic example because no receiver-dependent calculation can conceal the list. A function accepting only two named parameters may ignore the later values in its body, but the arguments were still supplied.
function collect(...values) { return values; }
const prepared = collect.bind(null, "red", "small");
prepared("blue", "large");
// ["red", "small", "blue", "large"]
Now change the target so its first parameter has a default. Binding undefined for that position supplies an undefined argument, which allows the target's parameter default to apply. Binding null supplies null, which does not trigger that default. Binding therefore determines the actual argument list; the target's parameter rules interpret those values afterward. Keeping those stages separate makes the outcome predictable without inventing a special defaulting rule for bind.
In a practical code review, write the full eventual argument list on one line. If a prepared factory unexpectedly treats a name as a quantity, check the stored prefix before inspecting the arithmetic inside the target. The error may be a position shift rather than a calculation error. Changing a parameter name or adding a comment will not repair a list that has been assembled in the wrong order.
CHAPTER 3 OF 14 · Trace ordinary calls
3. A later call cannot replace the stored ordinary-call receiver
Ordinary functions can often be invoked with call or apply to provide a receiver. A bound wrapper has already stored one for its target's ordinary call. Supplying a different receiver to the wrapper does not replace that stored choice. This is easiest to see by using two clearly different prefix objects and observing the target's returned string.
const south = { prefix: "South" };
labelBook.call(south, "Atlas"); // "North:book:Atlas"
labelBook.apply(south, ["Map"]); // "North:book:Map"
Both invocations still use desk. The later receiver reaches the bound wrapper's call operation, which forwards the stored receiver to the target instead. The later arguments remain useful: call passes Atlas, and apply supplies Map from its argument list. Receiver replacement and argument supply are separate questions. Failing to replace one does not mean that the entire later invocation was ignored.
Change the example by assigning labelBook to south's method property and calling it through that property. The result still uses North. A property-call expression can propose south as the receiver for the wrapper, but the bound wrapper continues to forward desk to the target. This is why looking only at the expression to the left of the final dot can be misleading when the value in the property is already bound.
Do not extend this rule to every kind of function without checking its behaviour. The statement here concerns how the bound wrapper forwards an ordinary call. The target may itself be an arrow function, another bound function or a function that never reads this. In those cases, the visible outcome depends on an additional layer. The reliable habit is to identify the actual target and trace each layer rather than treating a method-looking expression as a complete explanation.
A strict target also makes primitive receivers easier to reason about. In a strict ordinary function that simply returns this, binding null produces a call result of null, and binding the number seven produces the primitive seven. A non-strict ordinary target applies its own this-conversion rules, so null or undefined can become the global this value and primitives can be wrapped. Bind supplies the stored value to the target's call; it does not abolish the target's strictness rules. Use strict targets when the exercise is intended to compare receiver values directly, so a separate conversion does not obscure the central result.
This qualification matters when someone reports that a bound number appeared as an object in a console. Before concluding that binding copied or boxed the receiver itself, inspect the target's strictness and the way the result was displayed. A controlled strict target returning this removes most of that uncertainty. The next experiment can deliberately switch to a non-strict target, with the difference labelled as receiver conversion. Changing one assumption at a time makes a surprising observation useful rather than turning it into an unsupported rule about every bound function.
CHAPTER 4 OF 14 · Change preparation and operation
4. Rebinding adds a layer without replacing the first receiver
Calling bind on an already bound function creates another function object. It does not reach into the first wrapper and edit its stored receiver. During an ordinary call, the outer wrapper invokes the inner wrapper, and the inner wrapper still uses its own stored receiver for the original target. The first binding therefore continues to determine that target's ordinary-call this.
Arguments show the layers clearly. Use a target that returns a receiver label followed by the received values. The first binding stores receiver A and argument one. A second binding proposes receiver B and argument two. The eventual call supplies three. The original target sees receiver A and the argument order one, two, three. The second receiver is not used by the inner wrapper, but its stored argument is still forwarded.
function report(...values) {
"use strict";
return [this.id, ...values];
}
const first = report.bind({ id: "A" }, "one");
const second = first.bind({ id: "B" }, "two");
second("three"); // ["A", "one", "two", "three"]
A useful changed-context check removes the first receiver's id property after binding. The later call does not fall back to receiver B. It reads the current property value from receiver A and obtains undefined for that field. Binding did not establish a priority list of receivers to try. It stored a particular value, and the ordinary-call path continues to use it.
Repeated binding can be legitimate, but it can also conceal argument prefixes and make an API difficult to read. If the reader must reconstruct three nested preparation steps to understand one call, a named wrapper with explicit parameters may be clearer. That is a design choice, not a different language rule. The important check is whether the final target receives the intended receiver and list, regardless of which preparation style the program uses.
CHAPTER 5 OF 14 · Change preparation and operation
5. Bound objects remain live references
Binding an object stores that object value. It does not deep-copy its properties into a frozen receiver snapshot. If the target reads a property at call time, it sees the property's value at that time, subject to ordinary property access behaviour. This matters when the receiver represents settings that can change between preparation and use.
Return to desk and labelBook. Change desk.prefix from North to East, then call labelBook again. The result starts with East. The stored receiver is the same object, but one of its properties has changed. Now reassign the variable desk would require declaring it with let; such reassignment would point the variable at a different object without rewriting the receiver already stored in the wrapper. Mutation and variable reassignment are different operations.
const settings = { prefix: "First" };
const preparedLabel = label.bind(settings, "tool");
settings.prefix = "Later";
preparedLabel("Brush"); // "Later:tool:Brush"
The same reference principle applies to a stored argument that is an object. If a target later reads options.mode, changing that object before the call can change the result. The stored argument list contains values, and an object value refers to an object; it is not a recursive copy of the object's contents. If a stable snapshot is required, create one deliberately with an approach appropriate to the data, rather than assuming bind provides it.
For an evidence check, distinguish three questions: was a wrapper created, which object value was stored, and when were its properties read? A log of the final string answers only part of that sequence. A small controlled example with one property change reveals the timing. In application code, getters or proxies can add effects to a property read, so even retrieving a prefix may do more than inspect a passive field. Keep introductory tests on plain objects until that extra behaviour is the question.
There is another useful distinction between changing an object's property and replacing a variable. Declare a receiver variable with let, assign it an object whose prefix is Old, and bind label to that value. Reassign the variable to a new object whose prefix is New. A call through the existing wrapper still reads Old from the original object. The variable was consulted when binding evaluated its arguments; the wrapper does not remember an instruction to look up that variable again on every invocation. If the original object is retained through another reference and its prefix changes, that mutation can be observed. These are two different experiments and should have two different predictions.
Stored primitive arguments make the same timing visible without object mutation. If a variable holds a number when bind evaluates, the number is stored in the leading argument list. Reassigning the variable later does not update that stored number. By contrast, a wrapper written to read the variable inside its body can obtain the later value. Neither approach is universally better. One captures an argument value during preparation; the other performs a lookup during use. Choose according to whether the task requires a prepared value or the latest setting, and make that timing clear in the function's name or contract.
CHAPTER 6 OF 14 · Change preparation and operation
6. Change the operation to construction
Now introduce a constructable target. It assigns its arguments to this and does not return a replacement object. Bind it to a supplied record and a leading kind, then use new on the bound function. The leading kind remains part of the argument list. The supplied record does not become the instance, and the target's assignments go to the newly constructed object.
function Item(kind, name) {
this.kind = kind;
this.name = name;
}
const supplied = { marker: "keep" };
const Book = Item.bind(supplied, "book");
const atlas = new Book("Atlas");
// atlas.kind === "book"; atlas.name === "Atlas"
// supplied still has only marker
This is the central separation. Ordinary calling through a bound wrapper forwards the stored receiver. Construction through a constructable bound wrapper forwards construction to its target instead. The stored receiver is not used as the new object's this. The stored arguments are still prepended, so book appears in atlas.kind. Saying that new ignores the binding would be too broad: it ignores the bound receiver for this purpose, while retaining the argument prefix.
Compare an ordinary call using the same non-strict Item function in this controlled example. Calling Book with a name writes kind and name onto supplied, because the ordinary-call path uses the stored receiver. That call returns undefined here because Item has no explicit return. The two operations can therefore differ both in which object receives assignments and in what value is returned. A trace must include the operation, not merely the function's name.
A practical debugging record should inspect supplied before the ordinary call if the goal is to prove construction left it unchanged. Otherwise, a later ordinary call can legitimately modify it and make the earlier construction appear responsible. Order the observations carefully. The code's effects are sequential, and a final snapshot alone cannot tell us which invocation caused each property to appear.
CHAPTER 7 OF 14 · Check capabilities and identity
7. Construction depends on the target being constructable
Bind is not a machine for adding constructor capability to an arbitrary callable value. The bound function supports construction when its target does. An ordinary function declaration such as Item can be used as a constructor. An arrow function cannot. Binding an arrow therefore does not make new work, even when a plausible receiver object and arguments are supplied.
const arrow = value => ({ value });
const preparedArrow = arrow.bind({ ignored: true }, 7);
preparedArrow(); // { value: 7 }
// new preparedArrow(); // TypeError
Notice that the ordinary call still works and uses the stored leading argument. Constructability and callability are different capabilities. The fact that a function returns an object when called does not make it a constructor. The arrow above produces an object expression as its normal result; that is different from the language carrying out the construction operation requested by new.
Class constructors add another helpful comparison. A class can be constructable while rejecting an ordinary call without new. Binding its first argument does not remove that restriction. A bound class can support new while a plain invocation of the wrapper still fails when it reaches the class target. This prevents the opposite shortcut: assuming that every bound function must have a successful ordinary-call result.
When reviewing a prepared function, ask what its target supports and what operation the caller intends. A type-looking name beginning with a capital letter is a convention, not evidence of constructor capability. A returned object is also insufficient evidence. A controlled new invocation can establish runtime behaviour in a test, but production design should make the intended operation clear from the API contract rather than relying on trial-and-error calls with real side effects.
CHAPTER 8 OF 14 · Check capabilities and identity
8. Arrow functions retain their lexical this
An arrow function obtains this from its surrounding lexical context. Binding supplies a receiver to the wrapper, but the arrow's body does not adopt it as a new dynamic receiver. To make the context explicit, create the arrow inside an ordinary method call whose this is known. Avoid examples that rely on whether top-level this differs between a browser script and a module.
const source = {
id: "lexical",
make() { return () => this.id; }
};
const readId = source.make();
readId.bind({ id: "replacement" })(); // "lexical"
The arrow closes over the this established when source.make executes. Binding replacement later does not replace that lexical association. If source.id changes, the arrow can observe the changed property because it still reads the same source object. The lexical receiver rule and the live-object-reference rule work together; they do not promise a permanently frozen string.
Stored arguments can still affect a bound arrow's ordinary call. An arrow taking a value parameter can receive a prepended value just as the earlier preparedArrow example did. It is therefore inaccurate to say that bind does nothing to arrows. The receiver component cannot change the arrow's lexical this, while argument preparation remains meaningful. Separate the components before deciding whether a binding line has an effect.
A useful transfer exercise changes make from an ordinary method to an arrow stored as a property. That changes where its own this comes from and can alter the entire setup. Do not predict the result from the property name alone. For a concise production explanation, identify the ordinary call that establishes the enclosing this, then identify the arrow that captures it. If no such call exists in the presented code, the example needs more context before a definite receiver claim can be made.
CHAPTER 9 OF 14 · Check capabilities and identity
9. Trace instance prototypes separately from the bound receiver
For the normal Item construction example, the created instance inherits from Item.prototype. It does not inherit from supplied merely because supplied was used as the receiver in bind. Nor does the ordinary bound wrapper automatically have its own prototype property suitable for defining the instances' inheritance. These are different uses of the word prototype and deserve separate checks.
Object.getPrototypeOf(atlas) === Item.prototype; // true
Object.hasOwn(Book, "prototype"); // false
atlas instanceof Item; // true
atlas instanceof Book; // true
The last result can surprise a learner who expects instanceof to inspect only Book.prototype. For an ordinary bound function, the relevant instance check delegates through its bound target. In this controlled setup, atlas is recognised through both the wrapper and Item. This is not proof that the supplied receiver was used, and it is not a general promise about every customised instanceof implementation.
Add a property to Item.prototype after constructing atlas. An ordinary inherited lookup on atlas can see it, subject to normal prototype rules. Add a property to supplied instead, and atlas does not inherit it through this construction path. The difference provides a practical way to test competing mental models. One model predicts inheritance from the target's prototype; the other incorrectly predicts inheritance from the bound receiver.
Keep the limitations explicit. A constructor can return a different object, a custom newTarget can affect prototype selection, and special instance-check behaviour can alter a broader example. Those cases should be introduced as changes to the assumptions, not used to make the simple result sound unreliable. Under the stated ordinary setup, the result is definite. Good teaching states the setup precisely enough that both the result and its limits are understandable.
CHAPTER 10 OF 14 · Follow constructor outcomes
10. An explicit object return still matters
A constructor can explicitly return an object that becomes the result of construction instead of the default instance. Binding does not remove that ordinary constructor behaviour. Use a target that records its input in a replacement object and returns it. New through the bound wrapper still prepends the stored argument, but the resulting object follows the target's explicit return.
function Replacement(kind, name) {
this.unused = true;
return { kind, name, replacement: true };
}
const Prepared = Replacement.bind({ marker: "receiver" }, "map");
const result = new Prepared("Coast");
// { kind: "map", name: "Coast", replacement: true }
In this case, inspecting result does not reveal the temporary this object's unused property. That property was assigned during execution, but the constructor returned a different object. A learner who expects every new expression to return exactly the object initially used as this will misread the result. The explanation belongs to constructor return semantics, with bind contributing the argument prefix and forwarding behaviour.
Change the explicit return from an object to a primitive such as a string in an ordinary base-function constructor. The primitive does not replace the default constructed object. That contrast is useful, but it should not be carelessly generalised to derived class constructors, which have additional rules. Our example concerns an ordinary function constructor and makes that assumption visible.
For practical diagnosis, list the target's assignments and its explicit return separately. Ask which object each assignment affects, then ask which value construction ultimately produces. The two answers can refer to different objects. This method also discourages using instanceof as the only test of whether a preparation step worked. A legitimate constructor returning a separate plain object may produce a result that is not an instance of the target, even though the bound arguments were forwarded exactly as intended.
CHAPTER 11 OF 14 · Follow constructor outcomes
11. Read new.target with the forwarding rule in mind
A target can inspect new.target to distinguish construction from an ordinary call. In the straightforward new Book example, the bound construction operation forwards the original target as newTarget when the wrapper itself was the requested new target. The target therefore sees Item, not the bound wrapper, in the corresponding simple case. This is a specified forwarding detail, not a consequence of the wrapper's display name.
function Named(value) {
this.value = value;
this.seen = new.target;
}
const PreparedNamed = Named.bind(null, 12);
const named = new PreparedNamed();
named.seen === Named; // true
The stored null receiver plays no role in choosing the new instance here. The stored value twelve remains the first argument. Recording seen makes the construction path observable without relying on a console's presentation of a function name. Two functions can have similar names while being different objects, so equality against the actual target provides a stronger check than reading a printed label.
An advanced changed context uses Reflect.construct with a different newTarget. That deliberately changes the setup and can change the instance's prototype and what the target sees as new.target. The simple forwarding statement should therefore be stated with its condition: when construction directly requests the bound wrapper as newTarget. A reader does not need every reflective edge case to understand new Book, but should not turn that one example into a universal identity rule.
The broader debugging habit is to record hidden inputs when they matter. A constructor's visible arguments are not its only relevant context; the construction operation also carries newTarget. Bind stores some inputs and forwards others according to the operation. Naming those inputs explains why a seemingly identical target body can produce different outcomes under ordinary calls, direct construction and deliberately altered reflective construction.
CHAPTER 12 OF 14 · Follow constructor outcomes
12. Use a call-versus-construction ledger
Build a compact ledger for the Item example. The ordinary-call row records operation call, receiver supplied, arguments book then Atlas, return undefined, supplied gains fields. The construction row records operation new, receiver a constructed instance, arguments book then Atlas, return instance, supplied unchanged by that invocation. The shared argument prefix is as important as the differing receiver: it identifies exactly which part of the preparation survives both paths.
Now change only the later name from Atlas to Gazette. Both rows should show the new name while retaining book. Change the bound kind from book to poster and both rows should show poster. Change only the supplied receiver object and the ordinary-call effect moves to that object, while the ordinary construction result still follows the target's construction rules. These controlled changes test individual components instead of merely rerunning the same example.
A second ledger can compare an ordinary target, an arrow target and a class target. Record whether ordinary calling is allowed and whether construction is allowed before predicting any result. Then record whether the body uses dynamic this, lexical this or a construction-specific context. The purpose is not to memorise a table detached from code; it is to stop a capability assumption from slipping unnoticed into a trace.
When a test fails, classify the failure. An unexpected first argument suggests prefix order. An unexpected receiver during an ordinary call suggests an earlier binding or lexical capture. A TypeError from new may indicate a nonconstructable target. An unexpected returned object may come from an explicit constructor return. This classification narrows the next useful experiment and avoids changing unrelated code until a familiar output happens to appear.
| Operation | Target this | Argument prefix | Result |
|---|---|---|---|
| Book("Atlas") | Stored supplied object | book | undefined; writes supplied object |
| new Book("Atlas") | Constructed instance | book | Instance; supplied object unchanged by this invocation |
CHAPTER 13 OF 14 · Use and verify
13. Keep preparation distinct from application lifecycle
Every call to bind creates a function value, which matters when another API compares callback identity. An event listener registered with one bound function cannot generally be identified by creating a fresh bound function later and expecting it to be the same object. That lifecycle issue has its own detailed reading route. Here, it serves as a boundary: understanding receiver forwarding does not automatically establish that registration, cancellation or cleanup is correct.
Similarly, bind does not run validation, await asynchronous work, copy settings or guarantee that the target is free of side effects. A prepared function can throw when called, and effects performed before the throw are not undone by the fact that the function was bound. Preparation is a particular language operation, not a general safety wrapper around the target's behaviour.
For an application-facing design, choose a name that signals the intended use. A prepared ordinary callback and a prepared constructor may share a target mechanism but invite different operations from callers. If both are deliberately supported, document the difference in receiver effects. If only one is intended, exposing a broad callable value without explanation can make accidental ordinary calls or accidental new expressions harder to diagnose.
A practical review can be brief: identify the stored target and arguments; state the intended operation; check whether the receiver should remain live; inspect the target's return and side effects; then verify the separate API lifecycle if the value is registered elsewhere. Each question has a concrete purpose. This avoids treating bind as a mysterious permanent transformation and makes it easier to decide whether explicit wrapper code would be more readable for the actual reader.
A minimal failure experiment should also preserve evidence before it runs. Suppose a target writes a status field and then throws an error. A try block can catch the error, but it does not restore the receiver's previous status. Binding contributes neither a transaction nor a rollback mechanism. If the intended callback must leave state unchanged on failure, that behaviour must be designed into the target or its surrounding operation. A successful receiver test alone cannot establish it.
Avoid testing such effects on a shared production record merely to learn which path a function takes. A fresh local record and a target with one deliberate assignment provide a clearer result. Record the initial object, the invocation form, the caught error if any, and the final object. That four-part trace distinguishes failure to call from failure after a partial effect. It also prevents an exception message from hiding the state change that explains the next bug in a larger program.
For the final transfer, ask the learner to predict which observations would change if the receiver were replaced before binding rather than afterward. That contrast checks evaluation timing directly and makes a useful boundary visible without introducing a new API.
CHAPTER 14 OF 14 · Use and verify
14. Finish with an explanation that survives one changed input
A strong short explanation of new Book starts with the operation. Book is a bound wrapper around the constructable Item target. Its stored argument book is prepended to the later name. Construction forwards to Item and uses a constructed this rather than the stored supplied receiver. Because Item returns no replacement object, the result is the created instance with kind and name. Every clause corresponds to a checkable part of the example.
Now explain Book without new. The operation is an ordinary call, so the wrapper forwards supplied as this and uses the same argument prefix. Item writes onto supplied and returns undefined. The target body has not changed; the operation has. That is the key transfer. If a learner can explain both traces without saying that binding was either completely obeyed or completely ignored, the central distinction is secure.
For independent practice, replace Item with a constructor that returns a plain object, then replace it with an arrow that returns a plain object. Predict each ordinary call and new expression before running it. The returned-object cases look superficially alike, but their capabilities and construction results differ. Keep the predictions beside the observed results so that a corrected answer records the missing rule rather than only the final output.
The lasting method is to separate stored preparation from the operation that consumes it. Receiver forwarding, argument order, constructor capability, prototype selection and explicit return behaviour are connected without being interchangeable. A small ledger makes those connections visible. Once the operation is clear, a bound function stops being a special case to guess at and becomes a sequence that can be reasoned through, tested and explained in ordinary language.
Continue through the verified reading route
Callback lifecycle: repeated event-listener registration
Callback lifecycle: repeated event-listener registration. Binding prepares a function value; listener registration and later removal also depend on the actual function identity.
Receiver context: optional chains and grouped expressions
Receiver context: optional chains and grouped expressions. Use this for receiver-sensitive calls and short-circuit boundaries before deciding how explicit binding changes a call.
Property evidence: own presence and inherited lookup
Property evidence: own presence and inherited lookup. Use this when inspecting prototype properties without confusing a property value with an own-property claim.
Frequently asked questions
Does new ignore everything supplied to bind?
No. In construction through a constructable bound target, the bound receiver is ignored for the new instance, while stored arguments are still prepended.
Can call replace a bound receiver?
Not for the original target's ordinary-call path through that bound wrapper. The wrapper forwards its stored receiver, although the later call still supplies arguments.
Does binding an arrow make it a constructor?
No. A bound function is constructable only when its target is constructable. Arrows remain nonconstructable, and their lexical this is not replaced by binding.
Is the receiver copied when bind runs?
An object receiver is stored as an object value, not deep-copied. Later property changes can affect what the target reads when called.
Why can an instance satisfy instanceof for both target and bound function?
Ordinary bound-function instance checking delegates to the target. In the ordinary example, both checks recognise the instance; that does not mean it inherits from the bound receiver.
Should I bind again when removing an event listener?
A fresh binding creates a different function object. Keep the actual registered function value and follow the event API's matching rules. The linked listener-registration guide develops that separate lifecycle problem.
Authoritative sources and further reading
ECMAScript: bound-function call and construction. Normative receiver and argument forwarding, constructor capability and newTarget handling.
ECMAScript: Function.prototype.bind. Creation of the bound wrapper and the target requirements.
MDN: Function.prototype.bind. Reference examples and limitations for ordinary calls, repeated binding, arrows and construction.
Return to the Websites subject guide, The Gold Standard of Education, or the How X Works hub.