🤝 Object Methods in Action
Object methods are actions that can be performed on objects.
A method is a function definition stored as a property value:
const person = {
firstName: "John",
lastName: "Doe",
id: 5566,
fullName: function() {
return this.firstName + " " + this.lastName;
}
};✅ Explanation:
firstName,lastName, andidare properties with values.fullNameis a method (a function stored as a property).Inside the method,
this.firstNamerefers toperson.firstName.this.lastNamerefers toperson.lastName.
🗒️ Accessing Method:
let name = person.fullName();
console.log(name) // Output: John Doe()means the function is executed.If you just write
person.fullName(without()), it will return the function definition, not the result.
<div class="infographic-jsthis">
<style>
.infographic-jsthis {
--ink: #1a1a1a;
--ink-soft: #5c5c5c;
--paper: #ffffff;
--paper-alt: #f0ece4;
--line: #ddd6c9;
--accent: #2563eb;
--accent-soft:#e3ebfd;
--ok: #1a7f4e;
--ok-soft: #e3f5ec;
--display-font: 'Fraunces', Georgia, serif;
--body-font: 'Inter', -apple-system, sans-serif;
--mono-font: 'IBM Plex Mono', 'Courier New', 'Consolas', monospace;
margin: 0 auto;
box-sizing: border-box;
font-family: var(--body-font);
color: var(--ink);
background: var(--paper);
}
.infographic-jsthis[data-theme="dark"] {
--ink: #e8e6e1;
--ink-soft: #9a968c;
--paper: #121212;
--paper-alt: #1e1e26;
--line: #2c313d;
--accent: #5b8def;
--accent-soft:#202942;
--ok: #5cd6a0;
--ok-soft: #16342a;
}
.infographic-jsthis * { box-sizing: border-box; }
.infographic-jsthis .ig-inner { padding: 1.75rem clamp(1.25rem, 5vw, 3rem) 2rem; }
.infographic-jsthis .ig-title {
font-family: var(--display-font); font-size: clamp(1.4rem, 4.5vw, 1.9rem);
font-weight: 600; text-align: center; margin: 0 0 0.4rem;
}
.infographic-jsthis .ig-sub {
text-align: center; font-size: 0.85rem; color: var(--ink-soft); margin: 0 0 1.5rem;
}
.infographic-jsthis .chips { display: flex; flex-wrap: wrap; gap: 0.5rem; justify-content: center; margin-bottom: 1.25rem; }
.infographic-jsthis .chip {
font: inherit; font-size: 0.78rem; font-weight: 700; font-family: var(--mono-font);
border: 1px solid var(--line); background: var(--paper-alt); color: var(--ink);
padding: 0.4rem 0.75rem; border-radius: 999px; cursor: pointer;
}
.infographic-jsthis .chip.is-active { background: var(--accent); border-color: var(--accent); color: #fff; }
.infographic-jsthis .vscode-wrap { position: relative; margin-bottom: 1.1rem; }
.infographic-jsthis .vscode {
background: #1e1e1e; border-radius: 8px; overflow: hidden;
box-shadow: 0 8px 20px rgba(0,0,0,0.25); font-family: var(--mono-font);
border: 2px solid transparent; transition: border-color 0.3s ease, box-shadow 0.3s ease;
}
.infographic-jsthis .vscode.is-lit {
border-color: #f2c94c; box-shadow: 0 8px 20px rgba(0,0,0,0.25), 0 0 0 4px rgba(242,201,76,0.25);
}
.infographic-jsthis .window-badge {
position: absolute; top: -0.8rem; right: 0.8rem; z-index: 4;
font-family: var(--mono-font); font-size: 0.68rem; font-weight: 700;
background: #f2c94c; color: #3a2c00; padding: 0.25rem 0.6rem; border-radius: 999px;
opacity: 0; transform: translateY(-4px) scale(0.8); transition: opacity 0.3s ease, transform 0.3s ease;
box-shadow: 0 3px 8px rgba(0,0,0,0.3);
}
.infographic-jsthis .window-badge.is-visible { opacity: 1; transform: translateY(0) scale(1); }
.infographic-jsthis .vs-tabbar { display: flex; background: #252526; }
.infographic-jsthis .vs-tab {
display: flex; align-items: center; gap: 0.45rem; padding: 0.5rem 0.9rem;
background: #1e1e1e; border-top: 2px solid #f1e05a; font-size: 0.76rem; color: #d4d4d4;
}
.infographic-jsthis .vs-tab .dot { width: 0.5rem; height: 0.5rem; border-radius: 50%; background: #f1e05a; }
.infographic-jsthis .vs-body { padding: 0.9rem 1rem; }
.infographic-jsthis .vs-code { font-size: 0.78rem; line-height: 1.6; color: #d4d4d4; white-space: pre; }
.infographic-jsthis .kw { color: #569cd6; }
.infographic-jsthis .var { color: #9cdcfe; }
.infographic-jsthis .method { color: #dcdcaa; }
.infographic-jsthis .str { color: #ce9178; }
.infographic-jsthis .comment { color: #6a9955; }
.infographic-jsthis .punc { color: #d4d4d4; }
.infographic-jsthis .this-tok { color: #f2c94c; font-weight: 700; }
.infographic-jsthis .this-target {
border-radius: 3px; transition: background 0.3s ease, box-shadow 0.3s ease;
}
.infographic-jsthis .this-target.is-lit {
background: #4a3f0f; box-shadow: 0 0 0 3px #4a3f0f; outline: 1px solid #f2c94c;
}
.infographic-jsthis .run-row { display: flex; justify-content: center; margin-bottom: 1.1rem; }
.infographic-jsthis .run-btn {
font: inherit; font-size: 0.85rem; font-weight: 700; border: none; background: var(--accent);
color: #fff; padding: 0.55rem 1.2rem; border-radius: 999px; cursor: pointer;
}
.infographic-jsthis .run-btn:hover { opacity: 0.9; }
.infographic-jsthis .result-box {
border-radius: 8px; padding: 0.8rem 1rem; font-family: var(--mono-font); font-size: 0.85rem;
text-align: center; min-height: 1.4em; border: 1px solid var(--line); background: var(--paper-alt); color: var(--ink-soft);
}
.infographic-jsthis .result-box.is-live { border-color: var(--ok); background: var(--ok-soft); color: var(--ok); font-weight: 700; }
.infographic-jsthis .result-box .why { display: block; margin-top: 0.35rem; font-size: 0.76rem; font-weight: 400; color: var(--ink-soft); }
@media (prefers-reduced-motion: reduce) {
.infographic-jsthis *, .infographic-jsthis *::before, .infographic-jsthis *::after {
animation-duration: 0.001ms !important; transition-duration: 0.001ms !important;
}
}
</style>
<div class="ig-inner">
<h2 class="ig-title">Understanding <code>this</code></h2>
<p class="ig-sub"><code>this</code> depends on <strong>how a function is called</strong>, not where it's written</p>
<div class="chips" id="chips"></div>
<div class="vscode-wrap">
<span class="window-badge" id="windowBadge">🌐 window</span>
<div class="vscode" id="vscodeBlock">
<div class="vs-tabbar"><div class="vs-tab"><span class="dot"></span>script.js</div></div>
<div class="vs-body"><div class="vs-code" id="codeBlock"></div></div>
</div>
</div>
<div class="run-row"><button class="run-btn" id="runBtn">▶ Run</button></div>
<div class="result-box" id="resultBox">pick a scenario, then Run</div>
</div>
</div>
<script>
(function () {
const wrapper = document.currentScript.closest('.infographic-jsthis')
|| document.querySelector('.infographic-jsthis');
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 chipsEl = wrapper.querySelector('#chips');
const vscodeBlock = wrapper.querySelector('#vscodeBlock');
const windowBadge = wrapper.querySelector('#windowBadge');
const codeBlock = wrapper.querySelector('#codeBlock');
const runBtn = wrapper.querySelector('#runBtn');
const resultBox = wrapper.querySelector('#resultBox');
const SCENARIOS = [
{
id: 'method',
label: 'as a method',
code: `<span class="kw">const</span> obj = {
name: <span class="str">'Sam'</span>,
greet() { <span class="kw">return</span> <span class="this-tok">this</span>; }
};
<span class="kw">const</span> result = <span class="this-target" data-target="method">obj</span>.<span class="method">greet</span>();`,
run: () => {
const obj = { name: 'Sam', greet() { return this; } };
const result = obj.greet();
return { same: result === obj, label: 'obj', why: `<strong>this</strong> is whatever sits to the left of the dot when you call it — here, <strong>obj</strong>` };
}
},
{
id: 'plain',
label: 'plain call',
code: `<span class="kw">function</span> greet() { <span class="kw">return</span> <span class="this-tok">this</span>; }
<span class="kw">const</span> result = <span class="method">greet</span>();`,
wholeBlock: true,
run: () => {
function greet() { return this; }
const result = greet();
const globalObj = typeof window !== 'undefined' ? window : globalThis;
const isGlobal = result === globalObj;
return { same: isGlobal, label: 'the global object (window)', isWindow: isGlobal, why: `called with <strong>no owner object</strong> before the dot — in non-strict mode, this falls back to the global object` };
}
},
{
id: 'arrow',
label: 'arrow function',
code: `<span class="kw">const</span> obj = {
name: <span class="str">'Sam'</span>,
greet: () => { <span class="kw">return</span> <span class="this-tok">this</span>; }
};
<span class="kw">const</span> result = obj.<span class="method">greet</span>();`,
wholeBlock: true,
run: () => {
const obj = { name: 'Sam', greet: () => { return this; } };
const result = obj.greet();
const globalObj = typeof window !== 'undefined' ? window : globalThis;
const isWindow = result === globalObj;
const label = isWindow ? 'the global object (window) — NOT obj' : (result === obj ? 'obj' : 'the outer scope\'s this');
return { same: false, forcedLabel: label, isWindow, why: `arrow functions have <strong>no this of their own</strong> — they keep whatever this was outside them, ignoring how they're called` };
}
},
{
id: 'new',
label: 'new constructor',
code: `<span class="kw">function</span> Person(name) { <span class="this-tok">this</span>.name = name; }
<span class="kw">const</span> p = <span class="this-target" data-target="new"><span class="kw">new</span> <span class="method">Person</span>(<span class="str">'Sam'</span>)</span>;`,
run: () => {
function Person(name) { this.name = name; }
const p = new Person('Sam');
return { same: true, label: 'p (the new instance)', why: `<strong>new</strong> creates a fresh object and points <strong>this</strong> at it` };
}
},
{
id: 'bind',
label: 'call / apply / bind',
code: `<span class="kw">function</span> greet() { <span class="kw">return</span> <span class="this-tok">this</span>; }
<span class="kw">const</span> user = { name: <span class="str">'Sam'</span> };
<span class="kw">const</span> result = greet.<span class="method">call</span>(<span class="this-target" data-target="bind">user</span>);`,
run: () => {
function greet() { return this; }
const user = { name: 'Sam' };
const result = greet.call(user);
return { same: result === user, label: 'user (explicitly passed in)', why: `<strong>call()</strong> lets you set this yourself, overriding the normal rules` };
}
}
];
let current = SCENARIOS[0];
function renderCode() {
codeBlock.innerHTML = current.code;
resultBox.className = 'result-box';
resultBox.textContent = 'pick a scenario, then Run';
vscodeBlock.classList.remove('is-lit');
windowBadge.classList.remove('is-visible');
}
function selectScenario(sc) {
current = sc;
wrapper.querySelectorAll('.chip').forEach(c => c.classList.toggle('is-active', c.dataset.id === sc.id));
renderCode();
}
SCENARIOS.forEach((sc, i) => {
const chip = document.createElement('button');
chip.className = 'chip';
chip.textContent = sc.label;
chip.dataset.id = sc.id;
chip.addEventListener('click', () => selectScenario(sc));
chipsEl.appendChild(chip);
});
selectScenario(SCENARIOS[0]);
runBtn.addEventListener('click', () => {
const outcome = current.run();
const label = outcome.forcedLabel || outcome.label;
resultBox.className = 'result-box is-live';
resultBox.innerHTML = `this → <strong>${label}</strong><span class="why">${outcome.why}</span>`;
vscodeBlock.classList.remove('is-lit');
windowBadge.classList.remove('is-visible');
if (outcome.isWindow) {
void vscodeBlock.offsetWidth;
vscodeBlock.classList.add('is-lit');
windowBadge.classList.add('is-visible');
} else {
const target = codeBlock.querySelector('.this-target');
if (target) {
target.classList.remove('is-lit'); void target.offsetWidth; target.classList.add('is-lit');
}
}
});
})();
</script>.demo {
font-family: system-ui, sans-serif;
padding: 16px;
}
.demo h1 {
color: #2563eb;
margin: 0 0 8px;
}
.demo p {
color: #4b5563;
margin: 0;
}document.querySelector('.demo h1')?.addEventListener('click', () => {
alert('Hello from live preview!');
});The this keyword inside an object method refers to the object itself.
const person = {
firstName: "John",
lastName: "Doe",
fullName: function () {
return this.firstName + " " + this.lastName;
}
};
console.log(person.fullName()); //John DoeSo this.firstName + " " + this.lastName becomes "John" + " " + "Doe" = ”John Doe” .
❇️ Adding a Method to an Object Later
You can add new methods to an existing object after it's declared:
person.name = function () {
return this.firstName + " " + this.lastName;
};
console.log(person.name()); // Output: John Doe🔰 Using Built-in Methods Inside Object Methods
You can use built-in JavaScript string methods (like toUpperCase()) inside your own method:
person.name = function () {
return (this.firstName + " " + this.lastName).toUpperCase();
};
console.log(person.name()); // Output: JOHN DOE📝 Full Code Example:
const person = {
firstName: "John",
lastName: "Doe",
id: 5566,
fullName: function () {
return this.firstName + " " + this.lastName;
}
};
// Access method
console.log(person.fullName()); // John Doe
// Add new method
person.name = function () {
return this.firstName + " " + this.lastName;
};
console.log(person.name()); // John Doe
// Use JS method in custom method
person.name = function () {
return (this.firstName + " " + this.lastName).toUpperCase();
};
console.log(person.name()); // JOHN DOE