Objects: Properties, Methods & this
Object — property, method ও this
1. What Is an Object?
In JavaScript an object is an unordered collection of key → value pairs. Almost everything in JS that is not a primitive — arrays, functions, dates, regex, even modules — is an object under the hood. Mastering objects is therefore the single biggest step from "I know syntax" to "I can build software."
// An object literal — the most common way to make an object
const student = {
name: "Rahim",
age: 21,
department: "CSE",
isEnrolled: true
};
console.log(student);
console.log(`Hello ${student.name}, age ${student.age}`);
2. Property Access — Dot vs Bracket
There are two ways to read or write a property: dot notation (obj.key)
and bracket notation (obj["key"]). They do the same thing — but bracket
notation is required when the key is dynamic, contains spaces, or starts with a digit.
| Use | Dot | Bracket |
|---|---|---|
| Static key, valid identifier | ✅ user.name | ✅ user["name"] |
| Key in a variable | ❌ | ✅ user[key] |
| Key with space / dash | ❌ | ✅ obj["full name"] |
| Key that starts with a digit | ❌ | ✅ obj["404"] |
const user = { name: "Sadia", "home town": "Dhaka" };
console.log(user.name); // Sadia
console.log(user["home town"]); // Dhaka — dot would fail
const field = "name";
console.log(user[field]); // Sadia — dynamic key
// Reading a missing property returns undefined (not an error)
console.log(user.email); // undefined
3. Computed Property Names & Shorthand
ES6 added two ergonomics that you will use every day: computed property names
{[expr]: value} and property shorthand {x, y} when the
key and the variable share the same name.
const name = "Karim";
const age = 19;
// Old way
const v1 = { name: name, age: age };
// Shorthand — same effect, less noise
const v2 = { name, age };
// Computed key — the key is the value of an expression
const field = "score";
const v3 = { [field]: 95, [`${field}_max`]: 100 };
console.log(v2);
console.log(v3);
{name, age} মানে {name: name, age: age}। আর {[field]: 95}-এ field-এর মান (এখানে "score") key হিসেবে বসে। React, Redux ইত্যাদি library-তে এই দুটি pattern প্রতিদিন ব্যবহৃত হয়।
4. Methods — Functions That Live on Objects
A property whose value is a function is called a method. ES6 lets you write methods
without the function keyword — just name() { ... } inside the object
literal.
const account = {
owner: "Nadia",
balance: 5000,
// ES6 shorthand method — no `function` keyword
deposit(amount) {
this.balance += amount;
return this.balance;
},
withdraw(amount) {
if (amount > this.balance) return "Not enough funds";
this.balance -= amount;
return this.balance;
}
};
console.log(account.deposit(2000)); // 7000
console.log(account.withdraw(3000)); // 4000
console.log(account.balance); // 4000
5. The this Keyword — Four Binding Rules
this is the most misunderstood word in JavaScript. The trick: where
a function is called decides what this means — not where the function was
written. There are exactly four rules, applied in this priority order:
- new binding — called with
new f(),thisis the new instance. - Explicit binding —
f.call(obj),f.apply(obj), orf.bind(obj):thisisobj. - Implicit binding — called as
obj.f():thisisobj. - Default binding — plain
f():thisisundefinedin strict mode (or the global object in sloppy mode).
this-এর মান নির্ভর করে ফাংশনটি কীভাবে call হলো তার উপর — কোথায় লেখা হয়েছিল তাতে নয়। চারটি rule আছে — new, explicit (call/apply/bind), implicit (obj.f()), এবং default। এই priority অনুযায়ীই JS এই মান ঠিক করে।
function whoAmI() {
return this && this.label ? this.label : "<no label>";
}
const a = { label: "A", fn: whoAmI };
const b = { label: "B" };
console.log(a.fn()); // "A" — implicit
console.log(whoAmI.call(b)); // "B" — explicit
const bound = whoAmI.bind({ label: "C" });
console.log(bound()); // "C" — bind
// Losing `this`: pass the method as a callback
const looseRef = a.fn;
console.log(looseRef()); // "<no label>" — default
obj.method as a callback (e.g. setTimeout(obj.method, 100)) detaches
it from obj. By the time it runs, this is no longer your object. Fix with
.bind(obj) or wrap in an arrow function: setTimeout(() => obj.method(), 100).
6. Arrow Functions and Lexical this
Arrow functions are different. They do not get their own this — they inherit
this from the surrounding (lexical) scope where they were defined. This is exactly
what you usually want inside callbacks.
const timer = {
seconds: 0,
start() {
// Arrow inherits `this` from start() — so this.seconds works
const tick = () => {
this.seconds++;
console.log(`tick ${this.seconds}`);
};
tick(); tick(); tick();
}
};
timer.start();
// Output: tick 1, tick 2, tick 3
this to be the object the method is called on. Use an
arrow function inside callbacks where you want to keep the outer this.
7. Iterating Objects — keys / values / entries
for...in exists but iterates inherited keys too — usually not what you want. Prefer the
three Object static methods:
const prices = { rice: 75, oil: 180, sugar: 110 };
console.log(Object.keys(prices)); // ["rice","oil","sugar"]
console.log(Object.values(prices)); // [75,180,110]
console.log(Object.entries(prices)); // [["rice",75], ...]
let total = 0;
for (const [item, price] of Object.entries(prices)) {
console.log(`${item} = ${price}৳`);
total += price;
}
console.log(`Total = ${total}৳`);
Object.keys/values/entries — এই তিনটি method সবচেয়ে নিরাপদ ও আধুনিক উপায়। for...of-এর সাথে destructuring মিলিয়ে আপনি যেকোনো object-এর ওপর সহজে loop চালাতে পারেন।
8. Freezing, Sealing & Spread/Merge
Objects are mutable by default. JS gives you two locks: Object.freeze() (no add, no
change, no delete — fully immutable shallow lock) and Object.seal() (no add or delete,
but existing properties can still be changed).
"use strict";
const config = Object.freeze({ host: "localhost", port: 3000 });
try {
config.port = 8080; // silently ignored OR throws in strict mode
} catch (e) {
console.log("Frozen — cannot change: " + e.message);
}
console.log(config); // { host:'localhost', port:3000 }
const sealed = Object.seal({ a: 1 });
sealed.a = 99; // allowed
sealed.b = 2; // blocked — cannot add new keys
console.log(sealed); // { a: 99 }
Spread {...obj} creates a shallow copy and is the modern way to merge objects:
const defaults = { theme: "light", fontSize: 14, lang: "en" };
const userPrefs = { theme: "dark", fontSize: 16 };
// Later keys win — userPrefs override defaults
const settings = { ...defaults, ...userPrefs };
console.log(settings);
// { theme: 'dark', fontSize: 16, lang: 'en' }
9. Shallow vs Deep Copy — and structuredClone
Spread and Object.assign only copy one level deep. Nested objects are shared by
reference. Three options for a true deep copy, in increasing power:
JSON.parse(JSON.stringify(obj))
- Old trick — works for plain JSON-safe data
- Drops functions, dates become strings
- Throws on circular references
structuredClone(obj) ⭐ modern
- Built-in since 2022 (all modern browsers + Node 17+)
- Handles Map, Set, Date, ArrayBuffer, circular refs
- The new default deep clone
const original = {
name: "Tania",
address: { city: "Sylhet", zip: "3100" }
};
// Shallow copy — nested address is SHARED
const shallow = { ...original };
shallow.address.city = "Chattogram";
console.log(original.address.city); // "Chattogram" — leaked!
// Deep copy — completely independent
const deep = structuredClone(original);
deep.address.city = "Khulna";
console.log(original.address.city); // still "Chattogram"
console.log(deep.address.city); // "Khulna"
structuredClone()। পুরোনো কোডে JSON.parse(JSON.stringify()) দেখা গেলেও সেটির অনেক সীমাবদ্ধতা আছে।
10. Glossary (শব্দকোষ)
| Term | Meaning | বাংলায় |
|---|---|---|
| Object literal | Inline { key: value } syntax for creating an object. | সরাসরি { key: value } syntax-এ object তৈরি। |
| Property | A key-value pair on an object. | Object-এর key-value জোড়া। |
| Method | A function stored as a property of an object. | Object-এর property হিসেবে রাখা function। |
| Computed key | Dynamic property name written as [expr]. | Dynamic key — [expr] দিয়ে লেখা হয়। |
this | The receiver of a method call; one of 4 binding rules decides it. | Method-এর receiver — চারটি rule থেকে একটি প্রয়োগ হয়। |
bind | Returns a new function with this permanently fixed. | this নির্দিষ্ট করে নতুন function ফেরত দেয়। |
Spread ... | Expands properties; shallow copy/merge. | Property গুলোকে expand করে; shallow copy/merge। |
structuredClone | Built-in deep-clone for plain objects, arrays, dates, maps, sets. | Built-in deep-clone — nested object সব copy হয়। |
Object.freeze | Marks an object's own properties non-writable (shallow). | Top-level property গুলো immutable করে — shallow। |
Object.keys/values/entries দিয়ে iterate; merge-এ {...a, ...b}; deep-clone-এ structuredClone। this-এর চারটি rule (default, implicit, explicit/bind, new) মুখস্থ থাকলে অর্ধেক JS bug দূর হয়। Arrow function-এর নিজস্ব this নেই — তাই object method হিসেবে arrow ব্যবহার করবেন না।
11. Practice Problems
Try each problem yourself first, then click Show Answer to compare. Most answers are runnable right here in the browser.
-
Create an object
bookwith title, author and pages, and print each on its own line.title, author এবং pages-সহ একটিbookobject বানিয়ে প্রতিটি আলাদা লাইনে প্রিন্ট করুন।✨ Show Answer (উত্তর দেখুন)
ans1.jsconst book = { title: "Pother Panchali", author: "Bibhutibhushan", pages: 320 }; console.log(`Title : ${book.title}`); console.log(`Author: ${book.author}`); console.log(`Pages : ${book.pages}`); -
Given
const key = "score", create an object whose key isscoreand value is 90 — using a computed property name.computed property name ব্যবহার করে এমন object বানান যার key হবেscoreএবং মান 90।✨ Show Answer (উত্তর দেখুন)
ans2.jsconst key = "score"; const obj = { [key]: 90 }; console.log(obj); console.log(obj.score); -
Build a
rectangleobject with width, height, and anarea()method that usesthis.width, height এবং একটিarea()method-সহ একটিrectangleobject বানান, যেখানেthisব্যবহার করতে হবে।✨ Show Answer (উত্তর দেখুন)
ans3.jsconst rectangle = { width: 8, height: 5, area() { return this.width * this.height; } }; console.log(`Area = ${rectangle.area()}`); -
Use
Object.keysto count how many properties a given object has.Object.keysব্যবহার করে একটি object-এর কয়টি property আছে গণনা করুন।✨ Show Answer (উত্তর দেখুন)
ans4.jsconst obj = { a: 1, b: 2, c: 3, d: 4 }; console.log(`Property count = ${Object.keys(obj).length}`); -
Use
Object.entries+for...ofto print allkey = valuepairs of{ rice: 75, oil: 180, sugar: 110 }.Object.entriesওfor...ofদিয়ে object-এর প্রতিটি key-value প্রিন্ট করুন।✨ Show Answer (উত্তর দেখুন)
ans5.jsconst prices = { rice: 75, oil: 180, sugar: 110 }; for (const [k, v] of Object.entries(prices)) { console.log(`${k} = ${v}৳`); } -
Predict the output:
const f = obj.method; f();whenmethodusesthis.x. Why is the resultundefined?যখনmethod-এthis.xব্যবহার হয়,const f = obj.method; f();চালালে কেনundefinedআসে?✨ Show Answer (উত্তর দেখুন)
Answer: Detaching
obj.methodintofdrops the implicit binding. Callingf()uses default binding — in strict modethisisundefined, sothis.xthrows or yieldsundefined. Fix withconst f = obj.method.bind(obj).obj.method-কে আলাদা variable-এ রাখলে implicit binding চলে যায়। তখনthisdefault-এ চলে আসে — strict mode-এundefined। সমাধান:obj.method.bind(obj)। -
Show that
callandapplydo the same thing — only argument passing differs.প্রমাণ করুনcallএবংapplyএকই কাজ করে — শুধু argument পাঠানোর ভঙ্গি ভিন্ন।✨ Show Answer (উত্তর দেখুন)
ans7.jsfunction greet(g, p) { return `${g}, ${this.name}${p}`; } const me = { name: "Imran" }; console.log(greet.call(me, "Hello", "!")); console.log(greet.apply(me, ["Hello", "!"])); -
Demonstrate that an arrow function inside a method keeps the outer
this.প্রমাণ করুন method-এর ভিতরে arrow function বাইরেরthisধরে রাখে।✨ Show Answer (উত্তর দেখুন)
ans8.jsconst obj = { name: "Riya", delayedHi() { setTimeout(() => console.log(`Hi ${this.name}`), 10); } }; obj.delayedHi(); -
Make an object frozen and show that mutation in strict mode throws.একটি object freeze করে দেখান strict mode-এ mutation চেষ্টা করলে error হয়।
✨ Show Answer (উত্তর দেখুন)
ans9.js"use strict"; const p = Object.freeze({ pi: 3.14 }); try { p.pi = 3; } catch (e) { console.log("Error: " + e.message); } console.log(p.pi); -
Merge default settings with user settings using spread, and show user values win.spread দিয়ে default settings-এর ওপর user settings মিশিয়ে দেখান user-এর মান জেতে।
✨ Show Answer (উত্তর দেখুন)
ans10.jsconst defaults = { theme: "light", lang: "en", font: 14 }; const user = { theme: "dark", font: 18 }; const merged = { ...defaults, ...user }; console.log(merged); -
Show that a shallow spread copy of an object with a nested object still shares the nested reference.shallow copy করলে যে nested object reference share হয় — সেটি প্রমাণ করুন।
✨ Show Answer (উত্তর দেখুন)
ans11.jsconst a = { x: 1, nested: { y: 2 } }; const b = { ...a }; b.nested.y = 99; console.log(a.nested.y); // 99 — shared console.log(b.nested.y); // 99 -
Use
structuredCloneto deep-copy a nested object and prove the inner object is now independent.structuredCloneদিয়ে deep copy করে দেখান ভিতরের object আর share হয় না।✨ Show Answer (উত্তর দেখুন)
ans12.jsconst a = { nested: { y: 2 } }; const b = structuredClone(a); b.nested.y = 99; console.log(a.nested.y); // 2 — untouched console.log(b.nested.y); // 99 -
Build a
counterobject withvalue,inc(),dec(), andreset()methods.valueএবংinc/dec/resetmethod-সহ একটিcounterobject বানান।✨ Show Answer (উত্তর দেখুন)
ans13.jsconst counter = { value: 0, inc() { this.value++; return this; }, dec() { this.value--; return this; }, reset() { this.value = 0; return this; } }; counter.inc().inc().inc().dec(); console.log(counter.value); // 2 counter.reset(); console.log(counter.value); // 0 -
Demonstrate
Object.valueswithreduceto sum all numeric values of an object.Object.valuesএবংreduce-এ object-এর সব মান যোগ করে দেখান।✨ Show Answer (উত্তর দেখুন)
ans14.jsconst bills = { electric: 1200, gas: 450, internet: 800 }; const total = Object.values(bills).reduce((s, n) => s + n, 0); console.log(`Total bill = ${total}৳`); -
In one paragraph, explain why arrow functions are the wrong choice for object methods that need
this.কেন arrow function কোনো method-এthisদরকার হলে ব্যবহার করা উচিত নয় — এক অনুচ্ছেদে ব্যাখ্যা করুন।✨ Show Answer (উত্তর দেখুন)
Answer: Arrow functions inherit
thisfrom the enclosing lexical scope at the moment they are defined, not from how they are called. When you write a method as an arrow, that lexical scope is usually the module or the global scope — not the object — sothisends upundefinedinstead of the object you expected. Use a regular method (or shorthandname() {}) for object methods, and reserve arrows for inner callbacks.Arrow function-এ
thisঠিক হয় যেখানে এটি লেখা হয়েছে সেখান থেকে — যেখান থেকে call হচ্ছে সেখান থেকে নয়। তাই কোনো object-এর method হিসেবে arrow ব্যবহার করলেthisobject না হয়ে module বা global scope হয়ে যায়। তাই method লিখতে regular function বা shorthandname() {}ব্যবহার করুন; callback-এ arrow। -
Write a function
renameKey(obj, oldKey, newKey)that returns a new object with the key renamed (without mutating the input).renameKey(obj, oldKey, newKey)ফাংশন লিখুন যা mutate না করে একটি নতুন object দেবে যেখানে নাম বদল হয়েছে।✨ Show Answer (উত্তর দেখুন)
ans16.jsfunction renameKey(obj, oldKey, newKey) { const { [oldKey]: value, ...rest } = obj; return { ...rest, [newKey]: value }; } const u = { id: 1, name: "Mim", city: "Dhaka" }; console.log(renameKey(u, "name", "fullName")); console.log(u); // untouched
Summary — Module 13
An object is a bag of key→value pairs. Use dot notation for static keys, brackets for dynamic ones.
ES6 gives you shorthand and computed keys. Methods carry behavior.
this follows four binding rules — new > explicit > implicit > default —
and arrow functions break the chain by inheriting this lexically. Iterate with
Object.keys/values/entries, lock with freeze/seal, merge with spread, and
deep-copy with the modern structuredClone.
this-এর চারটি binding rule আছে — new, explicit, implicit, default — এবং arrow function lexical-ভাবে this ধার করে। Iterate-এ Object.keys/values/entries, লক করতে freeze/seal, merge-এ spread, আর deep clone-এ modern structuredClone।