تفاوت Reference و Primitive در جاوااسکریپت

فهرست مطالب

فهرست مطالب

آموزش کاملاً کاربردی، از ساده تا حرفه‌ای + مثال‌های واقعی پروژه‌ای

مقدمه

یکی از مهم‌ترین و حیاتی‌ترین مفاهیمی که یک دانشجوی جاوااسکریپت باید عمیقاً یاد بگیرد، تفاوت داده‌های Primitive و Reference است.

۹۰٪ باگ‌های تازه‌کارها و حتی برنامه‌نویسان سطح متوسط، دقیقاً از همین تفاوت ایجاد می‌شود.

مثلاً چرا این کد رفتار عجیبی دارد؟

const user1 = { name: "Ali" };
const user2 = user1;

user2.name = "Sara";

console.log(user1.name); // 😱 چرا شد "Sara" ؟!

اگر جواب را دقیق نمی‌دانید، این مقاله شما را نجات می‌دهد.

در این آموزش یاد می‌گیرید:

• Primitive و Reference دقیقاً چه هستند

• در حافظه چطور ذخیره می‌شوند

• چرا تغییر یک شیء، روی دیگری اثر می‌گذارد

• چطور کپی درست بگیریم (Shallow و Deep Copy)

• مثال‌های واقعی: فرم، API، سبد خرید، UI، LocalStorage

• اشتباهات رایج و روش حرفه‌ای کار با داده‌ها

تا آخر مقاله، این موضوع را لمس می‌کنید.

بخش ۱: قبل از هر چیز، Primitive چیست؟

Primitive یعنی داده‌ای که:

• مقدار مستقیم دارد

• کوچک و سبک است

• در Stack ذخیره می‌شود

• همیشه با مقدار کپی می‌شود (BY VALUE)

Primitiveها:

• string

• number

• boolean

• undefined

• null

• symbol

• bigint

بخش ۲: Reference چیست؟

Reference یعنی داده‌ای که:

• خودش مقدار نیست

• فقط آدرس یک داده را نگه می‌دارد

• داده اصلی در Heap ذخیره می‌شود

• هنگام نسبت دادن، آدرس کپی می‌شود (BY REFERENCE)

Referenceها:

• object

• array

• function

• date

• map / set

• regex

• هر نوع ساختار پیچیده

بخش ۳: فرق از نگاه حافظه (کاملاً تصویری و قابل لمس)

Primitive در حافظه

let a = 10;
let b = a;
b = 20;

معنی واقعی:

a → 10

b → 10 (کپی مقدار)

بعد b → 20 می‌شود ولی a دست‌نخورده باقی می‌ماند.

خروجی:

a = 10
b = 20

Reference در حافظه

const obj1 = { name: "Ali" };
const obj2 = obj1; // آدرس مشترک
obj2.name = "Sara";

در حقیقت:

obj1 → [Address: X]

obj2 → [Address: X]

و شیء اصلی داخل Heap است.

پس تغییر یکی یعنی تغییر دیگری.

بخش ۴: اولین مثال واقعی (فرم ثبت‌نام)

فرض کنید داده کاربر را ذخیره می‌کنید:

const user = {
    name: "",
    age: 0
};

function register(u) {
    u.name = "Ali";
    u.age = 19;
}
register(user);

نتیجه:

user = { name: "Ali", age: 19 }

چرا؟

چون تابع به جای مقدار، آدرس شیء را دریافت کرده.

این در پروژه‌های واقعی خیلی مهم است.

بخش ۵: مشکل بزرگ Reference – وقتی فکر می‌کنید کپی گرفته‌اید ولی نگرفته‌اید

مثال اشتباه بسیار رایج:

const original = { score: 10 };
const copy = original;

copy.score = 90;

console.log(original.score); // 90 😱

دانشجویان همیشه شوکه می‌شوند.

بخش ۶: آیا آرایه‌ها هم همین رفتار را دارند؟ بله!

const list1 = [1, 2, 3];
const list2 = list1;

list2.push(4);

console.log(list1); // [1,2,3,4] 😳

این دقیقاً Reference Behavior است.

بخش ۷: Shallow Copy – کپی سطحی (تا حدی مفید)

روش‌های کپی سطحی:

۱. اسپرد (Spread)

const copy = { ...original };

۲. Object.assign

const copy = Object.assign({}, original);

۳. آرایه:

const copyArr = [...list];

اما مشکل کپی سطحی:

اگر شیء تو در تو باشد، باز هم Reference می‌ماند.

const user = {
    name: "Ali",
    address: {
        city: "Tehran"
    }
};

const copy = { ...user };
copy.address.city = "Shiraz";

console.log(user.address.city); // Shiraz 😱

بخش ۸: Deep Copy – کپی واقعی و عمیق

بهترین روش‌های ۲۰۲۶:

۱. structuredClone (جدید و عالی)

const copy = structuredClone(user);

۲. JSON روش کلاسیک

const copy = JSON.parse(JSON.stringify(user));

(محدودیت دارد ولی کاربردی است)

بخش ۹: پروژه واقعی – مدیریت سبد خرید فروشگاه

در سبد خرید، یکی از رایج‌ترین باگ‌ها:

const cart = [];
const product = { id: 1, price: 200 };

cart.push(product);

const copy = product;
copy.price = 300;

کاربر قیمت محصول را در UI دستکاری می‌کند:

cart[0].price → 300 😱

برای رفع این مشکل:

cart.push(structuredClone(product));

بخش ۱۰: پروژه واقعی – مدیریت فرم در React / Vue / Angular

اگر با Reference اشتباه رفتار کنید، کامپوننت‌ها به‌طور ناخواسته رندر می‌شوند.

کد اشتباه:

setUser(newUser); // newUser با reference به قبلی

راه‌حل:

setUser({ ...newUser });

بخش ۱۱: مثال بسیار مهم – دستکاری ناخواسته شیء در تابع

اشتباه رایج:

function updateProduct(p) {
    p.price = 900;
}

updateProduct(product); // محصول اصلی خراب شد

راه‌حل:

function updateProduct(p) {
    const copy = { ...p };
    copy.price = 900;
    return copy;
}

بخش ۱۲: Primitive ها هیچ‌وقت این مشکل را ندارند

function changeAge(age) {
    age = 100;
}

let a = 20;
changeAge(a);

console.log(a); // 20

چون Primitive → مقدار کپی می‌شود.

بخش ۱۳: مثال بزرگ‌تر – مدیریت لیست Todo

const todos = [
    { id: 1, text: "Learn JS", done: false }
];

function complete(todo) {
    todo.done = true;
}

complete(todos[0]);

مشکل: داده اصلی تغییر می‌کند.

راه‌حل حرفه‌ای:

function complete(todo) {
    return { ...todo, done: true };
}

todos[0] = complete(todos[0]);

بخش ۱۴: Reference در ساختارهای پیچیده‌تر

Map

const map = new Map();
map.set("user", { name: "Sara" });

const u = map.get("user");
u.name = "Aysan";

console.log(map.get("user").name); // Aysan

Set

const set = new Set();
const obj = { a: 1 };
set.add(obj);

const x = obj;
x.a = 99;

console.log([...set][0].a); // 99

بخش ۱۵: اشتباهات رایج دانشجوها

❌ فکر می‌کنند = یعنی کپی واقعی

❌ فکر می‌کنند Spread همیشه Deep Copy است

❌ نمی‌دانند توابع Reference را تغییر می‌دهند

❌ در JSON و LocalStorage کپی درست نمی‌گیرند

❌ در React/Vue با Reference ناخواسته UI خراب می‌کنند

بخش ۱۶: روش حرفه‌ای مدیریت Reference

✓ همیشه برای ارسال به تابع، کپی بسازید

✓ اگر داده تو در تو است → Deep Copy

✓ برای UI → همیشه Immutable رفتار کنید

✓ هرگز Reference را بدون آگاهی پاس ندهید

✓ در React/Vue حتماً از ساختارهای جدید بسازید

بخش ۱۷: تمرین پروژه‌ای – ساخت سیستم مدیریت کاربر

const user = {
    name: "Ali",
    address: {
        city: "Tehran"
    }
};

function setCity(obj, city) {
    const u = structuredClone(obj);
    u.address.city = city;
    return u;
}

const updated = setCity(user, "Shiraz");

console.log(user.address.city); // Tehran
console.log(updated.address.city); // Shiraz

این تمرین را چند بار با داده‌های مختلف تکرار کنید.

نتیجه‌گیری

در این مقاله یاد گرفتید:

• Primitive کپی مقدار است

• Reference کپی آدرس است

• Reference در پروژه‌ها خطرناک است

• کپی سطحی همیشه کافی نیست

• کپی عمیق بهترین روش برای داده‌های پیچیده است

• در پروژه‌هایی مثل فروشگاه، Todo، فرم، UI، API → Reference بسیار مهم است

اگر این را دقیق یاد گرفته باشید، پایه‌ی ذهنی شما برای ادامه‌ی مسیر جاوااسکریپت بسیار قوی می‌شود.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *