In JavaScript, the value of this depends on how a function is called, not where it is written.
Sometimes we want to:
manually control
thisborrow a function from another object
permanently fix the value of
thisfor later use
That’s where call, apply, and bind help.
✅ call()
What it does
Calls a function immediately with a specific this value and arguments passed individually.
Syntax
func.call(thisArg, arg1, arg2, ...)✅ Example
const person = { name: "Bhaskar" };
function greet(city, country) {
console.log(`Hi, I'm ${this.name} from ${city}, ${country}`);
}
greet.call(person, "Kolkata", "India");<div class="infographic-callsyntax">
<style>
.infographic-callsyntax {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--good: #1a8a5f;
--good-soft: #e1f2ea;
box-sizing: border-box;
max-width: 880px;
margin: 0 auto;
font-family: 'Inter', system-ui, sans-serif;
color: var(--ink);
background: var(--paper);
overflow-x: hidden;
}
.infographic-callsyntax[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
--good: #4fbf8f;
--good-soft: #16281f;
}
.infographic-callsyntax * { box-sizing: border-box; }
.infographic-callsyntax h1 { font-family: 'Fraunces', Georgia, serif; font-weight: 600; margin: 0; }
.infographic-callsyntax p { margin: 0; }
.infographic-callsyntax button { font-family: inherit; }
.cs-wrap { padding: clamp(1.25rem, 5vw, 2.5rem) clamp(1.1rem, 5vw, 3rem) 2rem; }
.cs-hero { text-align: center; margin-bottom: 1.5rem; }
.cs-hero h1 { font-size: clamp(1.35rem, 4.5vw, 1.8rem); }
.cs-hero p { color: var(--ink-soft); margin-top: 0.45rem; font-size: 0.88rem; }
/* syntax strip */
.cs-syntax { display: flex; justify-content: center; align-items: center; gap: 0.3rem; flex-wrap: wrap; font-family: 'IBM Plex Mono', monospace; font-size: 0.88rem; margin-bottom: 0.3rem; }
.cs-syntax .punct { color: var(--ink-soft); }
.cs-tok { padding: 0.15rem 0.4rem; border-radius: 3px; }
.cs-tok.fnname { color: var(--ink); font-weight: 700; }
.cs-tok.thisarg { background: var(--accent-soft); color: var(--accent); font-weight: 700; }
.cs-tok.arg { background: var(--good-soft); color: var(--good); font-weight: 700; }
.cs-taglabels { display: flex; justify-content: center; gap: 1.6rem; margin-bottom: 1.6rem; flex-wrap: wrap; }
.cs-taglabel { font-size: 0.64rem; color: var(--ink-soft); text-align: center; }
.cs-taglabel .dot { display: inline-block; width: 8px; height: 8px; border-radius: 50%; margin-right: 0.3rem; vertical-align: middle; }
.cs-taglabel.this .dot { background: var(--accent); }
.cs-taglabel.args .dot { background: var(--good); }
/* diagram */
.cs-diagram { position: relative; width: 100%; max-width: 460px; margin: 0 auto; }
.cs-svg { width: 100%; height: auto; display: block; overflow: visible; }
.cs-path { fill: none; stroke: var(--line); stroke-width: 2.5; opacity: 0.4; }
.cs-path.is-active { opacity: 1; }
.cs-path.this-p.is-active { stroke: var(--accent); }
.cs-path.arg-p.is-active { stroke: var(--good); }
.cs-path.animate-in { stroke-dasharray: 220; stroke-dashoffset: 220; animation: csDraw 0.5s ease forwards; }
@keyframes csDraw { to { stroke-dashoffset: 0; } }
.cs-chip { position: absolute; text-align: center; padding: 0.35rem 0.55rem; border: 1.5px solid var(--line); background: var(--paper-alt); transform: translate(-50%, -50%); font-family: 'IBM Plex Mono', monospace; font-size: 0.68rem; font-weight: 700; transition: border-color 0.3s ease, background 0.3s ease; }
.cs-chip.this-chip.is-active { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
.cs-chip.arg-chip.is-active { border-color: var(--good); background: var(--good-soft); color: var(--good); }
.cs-fn-box { position: absolute; left: 50%; top: 82%; transform: translate(-50%, -50%); width: 260px; text-align: center; padding: 0.6rem 0.7rem; border: 1.5px solid var(--line); background: var(--paper-alt); }
.cs-fn-box .cs-fn-title { font-family: 'IBM Plex Mono', monospace; font-weight: 700; font-size: 0.76rem; }
.cs-fn-box .cs-fn-params { display: flex; justify-content: center; gap: 0.5rem; margin-top: 0.35rem; }
.cs-param { font-family: 'IBM Plex Mono', monospace; font-size: 0.66rem; padding: 0.15rem 0.4rem; border: 1px solid var(--line); color: var(--ink-soft); transition: border-color 0.3s ease, color 0.3s ease, background 0.3s ease; }
.cs-param.this-p.is-filled { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }
.cs-param.arg-p.is-filled { border-color: var(--good); color: var(--good); background: var(--good-soft); }
.cs-play { display: block; margin: 1.2rem auto 0; border: none; background: var(--accent); color: #fff; padding: 0.5rem 1.2rem; font-size: 0.8rem; font-weight: 600; cursor: pointer; }
.cs-play:active { transform: scale(0.96); }
.cs-play:disabled { opacity: 0.45; cursor: default; }
.cs-console {
margin: 1rem auto 0; max-width: 340px; text-align: left;
border: 1.5px solid var(--line); background: var(--paper-alt); padding: 0.5rem 0.8rem;
font-family: 'IBM Plex Mono', monospace; font-size: 0.72rem; display: flex; align-items: center; gap: 0.4rem;
}
.cs-console svg { width: 14px; height: 14px; stroke: var(--ink-soft); flex-shrink: 0; }
.cs-console .cs-out { color: var(--good); opacity: 0; transition: opacity 0.3s ease; }
.cs-console .cs-out.is-shown { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
.infographic-callsyntax *, .infographic-callsyntax *::before, .infographic-callsyntax *::after {
animation-duration: 0.001ms !important; transition-duration: 0.001ms !important;
}
}
</style>
<div class="cs-wrap">
<div class="cs-hero">
<h1>call() sends "this" and arguments, one by one</h1>
<p>Press play and watch each piece land in its slot.</p>
</div>
<div class="cs-syntax">
<span class="cs-tok fnname">greet</span><span class="punct">.call(</span><span class="cs-tok thisarg">person</span><span class="punct">, </span><span class="cs-tok arg">"Kolkata"</span><span class="punct">, </span><span class="cs-tok arg">"India"</span><span class="punct">)</span>
</div>
<div class="cs-taglabels">
<div class="cs-taglabel this"><span class="dot"></span>sets this</div>
<div class="cs-taglabel args"><span class="dot"></span>fill the parameters, in order</div>
</div>
<div class="cs-diagram">
<svg class="cs-svg" viewBox="0 0 460 200">
<path class="cs-path this-p" id="pathThis" d="M90,45 L150,150"></path>
<path class="cs-path arg-p" id="pathArg1" d="M230,45 L230,150"></path>
<path class="cs-path arg-p" id="pathArg2" d="M370,45 L310,150"></path>
</svg>
<div class="cs-chip this-chip" id="chipThis" style="left: 19%; top: 20%;">person</div>
<div class="cs-chip arg-chip" id="chipArg1" style="left: 50%; top: 20%;">"Kolkata"</div>
<div class="cs-chip arg-chip" id="chipArg2" style="left: 81%; top: 20%;">"India"</div>
<div class="cs-fn-box">
<div class="cs-fn-title">function greet(city, country)</div>
<div class="cs-fn-params">
<span class="cs-param this-p" id="paramThis">this</span>
<span class="cs-param arg-p" id="paramCity">city</span>
<span class="cs-param arg-p" id="paramCountry">country</span>
</div>
</div>
</div>
<button class="cs-play" id="csPlay" type="button">greet.call(person, "Kolkata", "India")</button>
<div class="cs-console">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m7 11 2-2-2-2"/><path d="M11 13h4"/><rect width="18" height="18" x="3" y="3" rx="2" ry="2"/></svg>
<span class="cs-out" id="csOut">Hi, I'm Bhaskar from Kolkata, India</span>
</div>
</div>
</div>
<script>
(function () {
const wrapper = document.currentScript.closest('.infographic-callsyntax')
|| document.querySelector('.infographic-callsyntax');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') { dark = true; }
else if (bodyAttr === 'false') { dark = false; }
else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
const playBtn = wrapper.querySelector('#csPlay');
const chips = [wrapper.querySelector('#chipThis'), wrapper.querySelector('#chipArg1'), wrapper.querySelector('#chipArg2')];
const paths = [wrapper.querySelector('#pathThis'), wrapper.querySelector('#pathArg1'), wrapper.querySelector('#pathArg2')];
const params = [wrapper.querySelector('#paramThis'), wrapper.querySelector('#paramCity'), wrapper.querySelector('#paramCountry')];
const out = wrapper.querySelector('#csOut');
playBtn.addEventListener('click', () => {
chips.forEach(c => c.classList.remove('is-active'));
paths.forEach(p => p.classList.remove('is-active', 'animate-in'));
params.forEach(p => p.classList.remove('is-filled'));
out.classList.remove('is-shown');
playBtn.disabled = true;
const STEP = 420;
chips.forEach((chip, i) => {
setTimeout(() => {
chip.classList.add('is-active');
paths[i].classList.add('is-active', 'animate-in');
}, i * STEP);
setTimeout(() => {
params[i].classList.add('is-filled');
}, i * STEP + 380);
});
setTimeout(() => {
out.classList.add('is-shown');
playBtn.disabled = false;
}, chips.length * STEP + 300);
});
})();
</script>✅ apply()
What it does
Works like call, but arguments are passed as an array.
Syntax
func.apply(thisArg, [arg1, arg2, ...])Example
greet.apply(person, ["Kolkata", "India"]);<div class="infographic-applyfn">
<style>
.infographic-applyfn {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--good: #1a8a5f;
--good-soft: #e1f2ea;
box-sizing: border-box;
max-width: 880px;
margin: 0 auto;
font-family: 'Inter', system-ui, sans-serif;
color: var(--ink);
background: var(--paper);
overflow-x: hidden;
}
.infographic-applyfn[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
--good: #4fbf8f;
--good-soft: #16281f;
}
.infographic-applyfn * { box-sizing: border-box; }
.infographic-applyfn h1, .infographic-applyfn h2 { font-family: 'Fraunces', Georgia, serif; font-weight: 600; margin: 0; }
.infographic-applyfn p { margin: 0; }
.infographic-applyfn button { font-family: inherit; }
.ap-wrap { padding: clamp(1.25rem, 5vw, 2.5rem) clamp(1.1rem, 5vw, 3rem) 2rem; }
.ap-hero { text-align: center; margin-bottom: 1.4rem; }
.ap-hero h1 { font-size: clamp(1.35rem, 4.5vw, 1.8rem); }
.ap-hero p { color: var(--ink-soft); margin-top: 0.45rem; font-size: 0.88rem; }
.ap-section { padding: 0.5rem 0 1.6rem; }
/* syntax strip */
.ap-syntax { display: flex; justify-content: center; align-items: center; gap: 0.25rem; flex-wrap: wrap; font-family: 'IBM Plex Mono', monospace; font-size: 0.86rem; margin-bottom: 1.2rem; }
.ap-syntax .punct { color: var(--ink-soft); }
.ap-tok { padding: 0.15rem 0.4rem; border-radius: 3px; }
.ap-tok.fnname { color: var(--ink); font-weight: 700; }
.ap-tok.thisarg { background: var(--accent-soft); color: var(--accent); font-weight: 700; }
.ap-tok.arr { background: var(--good-soft); color: var(--good); font-weight: 700; }
/* diagram 1: greet.apply */
.ap-diagram { position: relative; width: 100%; max-width: 440px; margin: 0 auto; }
.ap-svg { width: 100%; height: auto; display: block; overflow: visible; }
.ap-path { fill: none; stroke: var(--line); stroke-width: 2.5; opacity: 0.4; }
.ap-path.is-active { opacity: 1; }
.ap-path.this-p.is-active { stroke: var(--accent); }
.ap-path.arg-p.is-active { stroke: var(--good); }
.ap-path.animate-in { stroke-dasharray: 220; stroke-dashoffset: 220; animation: apDraw 0.5s ease forwards; }
@keyframes apDraw { to { stroke-dashoffset: 0; } }
.ap-chip { position: absolute; text-align: center; padding: 0.35rem 0.55rem; border: 1.5px solid var(--line); background: var(--paper-alt); transform: translate(-50%, -50%); font-family: 'IBM Plex Mono', monospace; font-size: 0.68rem; font-weight: 700; transition: border-color 0.3s ease, background 0.3s ease, opacity 0.3s ease; }
.ap-chip.this-chip.is-active { border-color: var(--accent); background: var(--accent-soft); color: var(--accent); }
.ap-chip.arr-chip { border-style: solid; }
.ap-chip.arr-chip.is-popped { opacity: 0.25; }
.ap-item { position: absolute; font-family: 'IBM Plex Mono', monospace; font-size: 0.64rem; font-weight: 700; color: var(--good); opacity: 0; transform: translate(-50%, -50%) scale(0.6); transition: opacity 0.35s ease, transform 0.35s ease; }
.ap-item.is-out { opacity: 1; transform: translate(-50%, -50%) scale(1); }
.ap-fn-box { position: absolute; left: 50%; top: 84%; transform: translate(-50%, -50%); width: 250px; text-align: center; padding: 0.6rem 0.7rem; border: 1.5px solid var(--line); background: var(--paper-alt); }
.ap-fn-box .ap-fn-title { font-family: 'IBM Plex Mono', monospace; font-weight: 700; font-size: 0.74rem; }
.ap-fn-box .ap-fn-params { display: flex; justify-content: center; gap: 0.5rem; margin-top: 0.35rem; }
.ap-param { font-family: 'IBM Plex Mono', monospace; font-size: 0.65rem; padding: 0.15rem 0.4rem; border: 1px solid var(--line); color: var(--ink-soft); transition: border-color 0.3s ease, color 0.3s ease, background 0.3s ease; }
.ap-param.this-p.is-filled { border-color: var(--accent); color: var(--accent); background: var(--accent-soft); }
.ap-param.arg-p.is-filled { border-color: var(--good); color: var(--good); background: var(--good-soft); }
.ap-play { display: block; margin: 1.2rem auto 0; border: none; background: var(--accent); color: #fff; padding: 0.5rem 1.2rem; font-size: 0.8rem; font-weight: 600; cursor: pointer; }
.ap-play:active { transform: scale(0.96); }
.ap-play:disabled { opacity: 0.45; cursor: default; }
.ap-console {
margin: 1rem auto 0; max-width: 320px; text-align: left;
border: 1.5px solid var(--line); background: var(--paper-alt); padding: 0.5rem 0.8rem;
font-family: 'IBM Plex Mono', monospace; font-size: 0.72rem; display: flex; align-items: center; gap: 0.4rem;
}
.ap-console svg { width: 14px; height: 14px; stroke: var(--ink-soft); flex-shrink: 0; }
.ap-console .ap-out { color: var(--good); opacity: 0; transition: opacity 0.3s ease; }
.ap-console .ap-out.is-shown { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
.infographic-applyfn *, .infographic-applyfn *::before, .infographic-applyfn *::after {
animation-duration: 0.001ms !important; transition-duration: 0.001ms !important;
}
}
</style>
<div class="ap-wrap">
<div class="ap-hero">
<h1>apply() — same idea, one array instead</h1>
<p>Identical to call(), except the arguments travel together in a single array.</p>
</div>
<div class="ap-section">
<div class="ap-syntax">
<span class="ap-tok fnname">greet</span><span class="punct">.apply(</span><span class="ap-tok thisarg">person</span><span class="punct">, </span><span class="ap-tok arr">["Kolkata", "India"]</span><span class="punct">)</span>
</div>
<div class="ap-diagram">
<svg class="ap-svg" viewBox="0 0 440 200">
<path class="ap-path this-p" id="pathThis" d="M90,45 L145,150"></path>
<path class="ap-path arg-p" id="pathArg1" d="M300,45 L215,150"></path>
<path class="ap-path arg-p" id="pathArg2" d="M300,45 L295,150"></path>
</svg>
<div class="ap-chip this-chip" id="chipThis" style="left: 20%; top: 20%;">person</div>
<div class="ap-chip arr-chip" id="chipArr" style="left: 68%; top: 20%;">[ "Kolkata", "India" ]</div>
<div class="ap-item" id="itemKolkata" style="left: 60%; top: 20%;">"Kolkata"</div>
<div class="ap-item" id="itemIndia" style="left: 76%; top: 20%;">"India"</div>
<div class="ap-fn-box">
<div class="ap-fn-title">function greet(city, country)</div>
<div class="ap-fn-params">
<span class="ap-param this-p" id="paramThis">this</span>
<span class="ap-param arg-p" id="paramCity">city</span>
<span class="ap-param arg-p" id="paramCountry">country</span>
</div>
</div>
</div>
<button class="ap-play" id="apPlay" type="button">greet.apply(person, [...])</button>
<div class="ap-console">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m7 11 2-2-2-2"/><path d="M11 13h4"/><rect width="18" height="18" x="3" y="3" rx="2" ry="2"/></svg>
<span class="ap-out" id="apOut">Hi, I'm Bhaskar from Kolkata, India</span>
</div>
</div>
</div>
</div>
<script>
(function () {
const wrapper = document.currentScript.closest('.infographic-applyfn')
|| document.querySelector('.infographic-applyfn');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') { dark = true; }
else if (bodyAttr === 'false') { dark = false; }
else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
/* greet.apply demo */
const playBtn = wrapper.querySelector('#apPlay');
const chipThis = wrapper.querySelector('#chipThis');
const chipArr = wrapper.querySelector('#chipArr');
const itemKolkata = wrapper.querySelector('#itemKolkata');
const itemIndia = wrapper.querySelector('#itemIndia');
const pathThis = wrapper.querySelector('#pathThis');
const pathArg1 = wrapper.querySelector('#pathArg1');
const pathArg2 = wrapper.querySelector('#pathArg2');
const paramThis = wrapper.querySelector('#paramThis');
const paramCity = wrapper.querySelector('#paramCity');
const paramCountry = wrapper.querySelector('#paramCountry');
const out = wrapper.querySelector('#apOut');
playBtn.addEventListener('click', () => {
[chipThis, chipArr].forEach(c => c.classList.remove('is-active', 'is-popped'));
[itemKolkata, itemIndia].forEach(i => i.classList.remove('is-out'));
[pathThis, pathArg1, pathArg2].forEach(p => p.classList.remove('is-active', 'animate-in'));
[paramThis, paramCity, paramCountry].forEach(p => p.classList.remove('is-filled'));
out.classList.remove('is-shown');
playBtn.disabled = true;
setTimeout(() => {
chipThis.classList.add('is-active');
pathThis.classList.add('is-active', 'animate-in');
}, 0);
setTimeout(() => paramThis.classList.add('is-filled'), 380);
setTimeout(() => {
chipArr.classList.add('is-popped');
itemKolkata.classList.add('is-out');
itemIndia.classList.add('is-out');
}, 500);
setTimeout(() => {
pathArg1.classList.add('is-active', 'animate-in');
pathArg2.classList.add('is-active', 'animate-in');
}, 650);
setTimeout(() => {
paramCity.classList.add('is-filled');
paramCountry.classList.add('is-filled');
}, 1030);
setTimeout(() => {
out.classList.add('is-shown');
playBtn.disabled = false;
}, 1350);
});
})();
</script>When useful
When arguments are already in an array
Example:
Math.max
console.log(Math.max.apply(null, [10, 3, 99])); // 99✅ bind()
What it does
Returns a new function with this permanently bound.
⚠️ It does NOT call the function immediately.
Syntax
const newFn = func.bind(thisArg, arg1, arg2, ...);Example
const sayHi = greet.bind(person, "Kolkata", "India");
sayHi(); // runs later<div class="infographic-bindfn">
<style>
.infographic-bindfn {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--line: #ddd6c9;
--good: #1a8a5f;
--good-soft: #e1f2ea;
--amber: #a4720a;
--amber-soft: #faf1de;
box-sizing: border-box;
max-width: 880px;
margin: 0 auto;
font-family: 'Inter', system-ui, sans-serif;
color: var(--ink);
background: var(--paper);
overflow-x: hidden;
}
.infographic-bindfn[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--accent: #5b8def;
--accent-soft:#202942;
--line: #2c313d;
--good: #4fbf8f;
--good-soft: #16281f;
--amber: #d9a94a;
--amber-soft: #2c2413;
}
.infographic-bindfn * { box-sizing: border-box; }
.infographic-bindfn h1 { font-family: 'Fraunces', Georgia, serif; font-weight: 600; margin: 0; }
.infographic-bindfn p { margin: 0; }
.infographic-bindfn button { font-family: inherit; }
.bn-wrap { padding: clamp(1.25rem, 5vw, 2.5rem) clamp(1.1rem, 5vw, 3rem) 2rem; }
.bn-hero { text-align: center; margin-bottom: 1.3rem; }
.bn-hero h1 { font-size: clamp(1.35rem, 4.5vw, 1.8rem); }
.bn-hero p { color: var(--ink-soft); margin-top: 0.45rem; font-size: 0.88rem; }
.bn-syntax { display: flex; justify-content: center; align-items: center; gap: 0.25rem; flex-wrap: wrap; font-family: 'IBM Plex Mono', monospace; font-size: 0.84rem; margin-bottom: 1.5rem; }
.bn-syntax .punct { color: var(--ink-soft); }
.bn-tok { padding: 0.15rem 0.4rem; border-radius: 3px; }
.bn-tok.fnname { color: var(--ink); font-weight: 700; }
.bn-tok.thisarg { background: var(--accent-soft); color: var(--accent); font-weight: 700; }
.bn-tok.arg { background: var(--good-soft); color: var(--good); font-weight: 700; }
.bn-tok.newname { background: var(--amber-soft); color: var(--amber); font-weight: 700; }
.bn-stage { display: flex; flex-direction: column; align-items: center; gap: 0; }
.bn-src { width: min(280px, 100%); text-align: center; border: 1.5px dashed var(--line); background: var(--paper-alt); padding: 0.55rem 0.7rem; }
.bn-src .bn-name { font-family: 'IBM Plex Mono', monospace; font-weight: 700; font-size: 0.75rem; }
.bn-src .bn-sub { font-size: 0.6rem; color: var(--ink-soft); margin-top: 0.1rem; }
.bn-link { width: 2px; height: 34px; background: var(--line); position: relative; }
.bn-link-fill { position: absolute; left: 0; top: 0; width: 2px; height: 0%; background: var(--amber); transition: height 0.5s ease; }
.bn-link-label { font-family: 'IBM Plex Mono', monospace; font-size: 0.6rem; color: var(--ink-soft); text-align: center; margin: 0.15rem 0; opacity: 0.5; transition: opacity 0.3s ease, color 0.3s ease; }
.bn-link-label.is-lit { opacity: 1; color: var(--amber); font-weight: 600; }
.bn-sealed {
width: min(300px, 100%); text-align: center; border: 1.5px solid var(--line); background: var(--paper-alt);
padding: 0.6rem 0.7rem; position: relative; opacity: 0.3; transform: scale(0.92);
transition: opacity 0.4s ease, transform 0.4s ease, border-color 0.4s ease, background 0.4s ease;
}
.bn-sealed.is-created { opacity: 1; transform: scale(1); border-color: var(--amber); background: var(--amber-soft); }
.bn-sealed .bn-lock { position: absolute; top: -10px; right: -10px; width: 22px; height: 22px; border-radius: 50%; background: var(--paper); border: 1.5px solid var(--line); display: flex; align-items: center; justify-content: center; opacity: 0; transition: opacity 0.3s ease, border-color 0.3s ease; }
.bn-sealed .bn-lock svg { width: 12px; height: 12px; stroke: var(--ink-soft); }
.bn-sealed.is-created .bn-lock { opacity: 1; border-color: var(--amber); }
.bn-sealed.is-created .bn-lock svg { stroke: var(--amber); }
.bn-sealed .bn-name { font-family: 'IBM Plex Mono', monospace; font-weight: 700; font-size: 0.78rem; }
.bn-sealed .bn-sub { font-size: 0.62rem; color: var(--ink-soft); margin-top: 0.15rem; }
.bn-sealed .bn-status { display: inline-flex; align-items: center; gap: 0.3rem; margin-top: 0.4rem; font-size: 0.62rem; padding: 0.15rem 0.45rem; border: 1px solid var(--line); }
.bn-sealed .bn-status svg { width: 11px; height: 11px; stroke: var(--ink-soft); }
.bn-sealed .bn-status.waiting { color: var(--ink-soft); }
.bn-sealed .bn-status.ran { color: var(--good); border-color: var(--good); background: var(--good-soft); }
.bn-sealed .bn-status.ran svg { stroke: var(--good); }
.bn-controls { display: flex; flex-wrap: wrap; gap: 0.6rem; justify-content: center; margin-top: 1.2rem; }
.bn-btn { border: none; padding: 0.5rem 1.1rem; font-size: 0.8rem; font-weight: 600; cursor: pointer; }
.bn-btn.primary { background: var(--accent); color: #fff; }
.bn-btn.secondary { background: var(--good); color: #fff; }
.bn-btn:disabled { opacity: 0.4; cursor: default; }
.bn-btn:active:not(:disabled) { transform: scale(0.96); }
.bn-console {
margin: 1rem auto 0; max-width: 320px; text-align: left;
border: 1.5px solid var(--line); background: var(--paper-alt); padding: 0.5rem 0.8rem;
font-family: 'IBM Plex Mono', monospace; font-size: 0.72rem; display: flex; align-items: center; gap: 0.4rem;
}
.bn-console svg { width: 14px; height: 14px; stroke: var(--ink-soft); flex-shrink: 0; }
.bn-console .bn-out { color: var(--good); opacity: 0; transition: opacity 0.3s ease; }
.bn-console .bn-out.is-shown { opacity: 1; }
.bn-note { text-align: center; font-size: 0.78rem; color: var(--ink-soft); margin-top: 1.4rem; padding-top: 1rem; border-top: 1px dashed var(--line); }
.bn-note strong { color: var(--ink); }
@media (prefers-reduced-motion: reduce) {
.infographic-bindfn *, .infographic-bindfn *::before, .infographic-bindfn *::after {
animation-duration: 0.001ms !important; transition-duration: 0.001ms !important;
}
}
</style>
<div class="bn-wrap">
<div class="bn-hero">
<h1>bind() locks "this" in — but waits</h1>
<p>It hands you a new function. Nothing runs until you call that.</p>
</div>
<div class="bn-syntax">
<span class="bn-tok newname">sayHi</span><span class="punct"> = </span><span class="bn-tok fnname">greet</span><span class="punct">.bind(</span><span class="bn-tok thisarg">person</span><span class="punct">, </span><span class="bn-tok arg">"Kolkata"</span><span class="punct">, </span><span class="bn-tok arg">"India"</span><span class="punct">)</span>
</div>
<div class="bn-stage">
<div class="bn-src">
<div class="bn-name">function greet(city, country)</div>
<div class="bn-sub">this.name, city, country — unbound</div>
</div>
<div class="bn-link">
<div class="bn-link-fill" id="bindFill"></div>
</div>
<div class="bn-link-label" id="bindLabel">.bind(person, "Kolkata", "India")</div>
<div class="bn-sealed" id="sealedFn">
<div class="bn-lock">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect width="18" height="11" x="3" y="11" rx="2" ry="2"/><path d="M7 11V7a5 5 0 0 1 10 0v4"/></svg>
</div>
<div class="bn-name">const sayHi</div>
<div class="bn-sub">this, city, country — all locked in</div>
<div class="bn-status waiting" id="bindStatus">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg>
created — not run yet
</div>
</div>
</div>
<div class="bn-controls">
<button class="bn-btn primary" id="bindBtn" type="button">greet.bind(person, ...)</button>
<button class="bn-btn secondary" id="runBtn" type="button" disabled>sayHi()</button>
</div>
<div class="bn-console">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="m7 11 2-2-2-2"/><path d="M11 13h4"/><rect width="18" height="18" x="3" y="3" rx="2" ry="2"/></svg>
<span class="bn-out" id="bnOut">Hi, I'm Bhaskar from Kolkata, India</span>
</div>
<p class="bn-note"><strong>call()</strong> and <strong>apply()</strong> run right away. <strong>bind()</strong> just packages everything up — you decide when <strong>sayHi()</strong> actually fires.</p>
</div>
</div>
<script>
(function () {
const wrapper = document.currentScript.closest('.infographic-bindfn')
|| document.querySelector('.infographic-bindfn');
const bodyAttr = document.body.getAttribute('data-darkmode');
let dark;
if (bodyAttr === 'true') { dark = true; }
else if (bodyAttr === 'false') { dark = false; }
else {
const match = document.cookie.match(/(?:^|;\s*)darkMode=([^;]+)/);
dark = match ? match[1] === 'true' : false;
}
if (dark) wrapper.setAttribute('data-theme', 'dark');
const bindBtn = wrapper.querySelector('#bindBtn');
const runBtn = wrapper.querySelector('#runBtn');
const fill = wrapper.querySelector('#bindFill');
const label = wrapper.querySelector('#bindLabel');
const sealed = wrapper.querySelector('#sealedFn');
const status = wrapper.querySelector('#bindStatus');
const out = wrapper.querySelector('#bnOut');
function resetAll() {
fill.style.transition = 'none';
fill.style.height = '0%';
void fill.offsetWidth;
fill.style.transition = 'height 0.5s ease';
label.classList.remove('is-lit');
sealed.classList.remove('is-created');
status.classList.remove('ran');
status.classList.add('waiting');
status.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></svg> created — not run yet';
out.classList.remove('is-shown');
runBtn.disabled = true;
}
bindBtn.addEventListener('click', () => {
resetAll();
setTimeout(() => {
fill.style.height = '100%';
label.classList.add('is-lit');
}, 60);
setTimeout(() => {
sealed.classList.add('is-created');
}, 500);
setTimeout(() => {
runBtn.disabled = false;
}, 800);
});
runBtn.addEventListener('click', () => {
status.classList.remove('waiting');
status.classList.add('ran');
status.innerHTML = '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M20 6 9 17l-5-5"/></svg> ran just now';
out.classList.add('is-shown');
});
})();
</script>Use cases
Fix
thisinside callbacksReact event handlers (common!)
Delayed function execution
🧠 Whats happening behind the scene
const person = { name: "Bhaskar" };
function greet(city, country) {
console.log(`Hi, I'm ${this.name} from ${city}, ${country}`);
}
greet.call(person, "Kolkata", "India");greet.call(person, "Kolkata", "India")
✔️ It calls the greet function
✔️ It sets this inside greet to person
✔️ It passes the arguments "Kolkata" and "India"
So inside the function, JavaScript treats it as:
this.name → person.name → "Bhaskar"
city → "Kolkata"
country → "India"And it behaves like you wrote:
console.log("Hi, I'm Bhaskar from Kolkata, India");Same for apply() and bind()
🔥 Comparison Table
Feature |
|
|
|
|---|---|---|---|
Executes immediately | ✅ Yes | ✅ Yes | ❌ No |
How arguments are passed | individually | array | individually (optional) |
Returns | function result | function result | new function |
Use case | quick manual call | when args in array | save for later |
⚠️ Common Mistakes
✅ bind does not call the function
greet.bind(person); // nothing happens yet✅ apply requires array-like, not individual values
greet.apply(person, "Kolkata", "India"); // ❌ error✅ Arrow functions ignore call/apply/bind
const arrow = () => console.log(this);
arrow.call({ a: 10 }); // still global `this`