یک عملگر انتساب، بر اساس مقدارِ سمت راست خود، مقداری را به عملوند سمت چپش اختصاص میدهد. عملگر انتسابِ ساده همان مساوی (=) است که مقدار سمت راست را به عملوند سمت چپ میفرستد. به عنوان مثال، عبارت x = f() یک عبارت انتساب است که مقدارِ خروجی تابع f() را به x اختصاص میدهد.
جاوااسکریپت عملگرهای انتساب ترکیبی (Compound assignment operators) نیز دارد که به عنوان شکل خلاصه شدهی عملیاتهای جدول زیر استفاده میشوند:
| نام عملگر | شکل خلاصه شده | معنا و مفهوم |
| انتساب (Assignment) | x = f() | x = f() |
| انتساب جمع | x += f() | x = x + f() |
| انتساب تفریق | x -= f() | x = x - f() |
| انتساب ضرب | x *= f() | x = x * f() |
| انتساب تقسیم | x /= f() | x = x / f() |
| انتساب باقیمانده | x %= f() | x = x % f() |
| انتساب توان | x **= f() | x = x ** f() |
| انتساب شیفت به چپ | x <<= f() | x = x << f() |
| انتساب شیفت به راست | x >>= f() | x = x >> f() |
| انتساب شیفت به راست بدون علامت | x >>>= f() | x = x >>> f() |
| انتساب AND بیتی | x &= f() | x = x & f() |
| انتساب XOR بیتی | x ^= f() | x = x ^ f() |
| انتساب OR بیتی | `x | = f()` |
| انتساب AND منطقی | x &&= f() | x && (x = f()) |
| انتساب OR منطقی | `x | |
| انتساب نفیدوگانه (Nullish) | x ??= f() | x ?? (x = f()) |
اگر خروجی یک عبارت یک «شیء» (Object) باشد، میتوان به ویژگیهای (Properties) آن شیء مقدار داد:
const obj = {};
obj.x = 3;
console.log(obj.x); // عدد 3 را چاپ میکند
console.log(obj); // مقدار { x: 3 } را چاپ میکند
const key = "y";
obj[key] = 5;
console.log(obj[key]); // عدد 5 را چاپ میکند
console.log(obj); // مقدار { x: 3, y: 5 } را چاپ میکند
اما اگر خروجی یک عبارت شیء نباشد، تلاش برای مقداردهی به ویژگیهای آن بینتیجه خواهد بود:
const val = 0;
val.x = 3;
console.log(val.x); // مقدار undefined را چاپ میکند
console.log(val); // همان عدد 0 را چاپ میکند
در حالت Strict Mode، کد بالا ارور میدهد؛ چرا که نمیتوان به ویژگیهای مقادیر اولیه (Primitives) مقداری اختصاص داد. همچنین مقداردهی به ویژگیهای غیرقابل تغییر (Unmodifiable) یا ویژگیهای عباراتی که اصلاً ویژگی ندارند (مثل null یا undefined) خطا محسوب میشود.
برای انتسابهای پیچیدهتر، ساختار Destructuring به ما این امکان را میدهد تا دادهها را از درون آرایهها یا اشیاء، با ساختاری که دقیقاً شبیه به ظاهر خودِ آرایهها و اشیاء است، بیرون بکشیم.
بدون استفاده از این قابلیت، بیرون کشیدن مقادیر به چند خط کد نیاز دارد:
const foo = ["one", "two", "three"];
const one = foo[0];
const two = foo[1];
const three = foo[2];
اما با کمک قابلیت Destructuring، میتوانید چندین مقدار را تنها در یک خط کد درون متغیرهای مجزا قرار دهید:
const [one, two, three] = foo;
به طور کلی، انتسابها در زمان تعریف متغیرها (با const ،let یا var) یا به عنوان دستورات مستقل استفاده میشوند:
// متغیر x تعریف شده و با خروجی تابع f() مقداردهی اولیه میشود
// نتیجهی نهایی خودِ عبارت انتساب x = f() دور ریخته میشود
let x = f();
x = g(); // مقدار متغیر x با خروجی تابع g() جایگزین میشود
با این حال، عبارتهای انتساب مثل x = f() خودشان به یک مقدار نهایی ارزیابی میشوند. اگرچه این مقدار معمولاً استفاده نمیشود، اما میتواند توسط عبارت دیگری به کار گرفته شود.
زنجیر کردن انتسابها یا تو در تو نوشتن آنها میتواند رفتارهای غیرمنتظرهای ایجاد کند. به همین دلیل، برخی راهنماهای کدنویسی جاوااسکریپت این کار را توصیه نمیکنند. با این حال، درک نحوه کارکرد آنها برای زمانهایی که با چنین کدهایی مواجه میشوید مهم است.
با زنجیر کردن یا تو در تو نوشتن یک عبارت انتساب، مقدار نهایی آن را میتوان به متغیر دیگری داد، آن را لاگ کرد، یا درون یک آرایه و فرم صدا زدن تابع قرار داد:
let x;
const y = (x = f()); // یا به شکل معادل: const y = x = f();
console.log(y); // مقدار خروجی حاصل از انتساب x = f() را لاگ میکند
console.log(x = f()); // مقدار نهایی را مستقیماً لاگ میکند
// یک عبارت انتساب میتواند در هر جایی که استفاده از عبارات مجاز است (مثل اعضای آرایه یا ورودی توابع) قرار بگیرد
console.log([0, x = f(), 0]);
console.log(f(0, x = f(), 0));
نتیجهی نهایی ارزیابی، با مقدار سمت راست علامت = در ستون «معنا و مفهوم» جدول بالا مطابقت دارد. این یعنی x = f() به همان مقدار خروجی f() ارزیابی میشود، x += f() به حاصلجمع x + f() ارزیابی میشود، x = f() به حاصل توان x f() ارزیابی میشود و به همین ترتیب ادامه مییابد.
در مورد انتسابهای منطقی یعنی x &&= f() ،x ||= f() و x ??= f()، مقدار برگشتی دقیقاً همان خروجی عملیات منطقی بدون انتساب است؛ یعنی به ترتیب معادل با x && f() ،x || f() و x ?? f() میباشند.
هنگام زنجیر کردن این عبارات بدون استفاده از پرانتز یا بقیه ابزارهای گروهبندی (مانند آرایهها)، این عبارات از راست به چپ گروهبندی میشوند (حقتداعی یا Right-associative هستند)، اما ارزیابی و اجرای آنها از چپ به راست انجام میشود.
توجه داشته باشید که در تمام عملگرهای انتساب ترکیبی (به جز خودِ =)، مقادیر نهایی همیشه بر اساس مقدار عملوندها قبل از انجام عملیات محاسبه میشوند.
برای بررسی دقیقتر، فرض کنید توابع f و g و متغیرهای x و y به این صورت تعریف شدهاند:
function f() {
console.log("F!");
return 2;
}
function g() {
console.log("G!");
return 3;
}
let x, y;
بیا سه مثال زیر را قدم به قدم بررسی کنیم:
y = x = f()این عبارت به دلیل خاصیت حقتداعی عملگر = با عبارت y = (x = f()) معادل است، اما ارزیابی آن از چپ به راست رخ میدهد:
عبارت انتساب y = x = f() شروع به ارزیابی میکند. متغیر y در سمت چپ، به عنوان ارجاعی به متغیر y شناسایی میشود.
عبارت داخلی x = f() شروع به ارزیابی میکند. متغیر x در سمت چپ، به عنوان ارجاعی به متغیر x شناسایی میشود.
تابع f() صدا زده شده، متن "!F" را چاپ میکند و به عدد ۲ ارزیابی میشود.
عدد ۲ حاصل از تابع، به x اختصاص مییابد.
کار ارزیابی عبارت x = f() تمام میشود؛ نتیجهی آن همان مقدار جدید x یعنی عدد ۲ است.
این عدد ۲ به متغیر y نیز اختصاص داده میشود.
کل عبارت تمام میشود؛ نتیجهی نهایی مقدار جدید y یعنی همان عدد ۲ است. متغیرهای x و y هر دو برابر با ۲ شدهاند و در کنسول عبارت "!F" چاپ شده است.
y = [ f(), x = g() ]این ساختار نیز از چپ به راست ارزیابی میشود:
عبارت انتساب اصلی شروع میشود و y سمت چپ، به عنوان ارجاعی به متغیر y شناسایی میشود.
آرایهی داخلی [ f(), x = g() ] شروع به ارزیابی میکند.
تابع f() اجرا شده، متن "!F" را چاپ میکند و به عدد ۲ تبدیل میشود.
عبارت انتساب x = g() شروع به ارزیابی میکند و x ارجاع داده میشود.
تابع g() اجرا شده، متن "!G" را چاپ میکند و به عدد ۳ تبدیل میشود.
عدد ۳ به متغیر x اختصاص داده میشود.
ارزیابی عبارت x = g() تمام میشود و نتیجهی آن یعنی عدد ۳، به عنوان عضو بعدی آرایه (بعد از عدد ۲ حاصل از f) قرار میگیرد.
ارزیابی آرایه تمام شده و خروجی آن یک آرایه با دو عضو است: [ 2, 3 ].
آرایهی [ 2, 3 ] به متغیر y اختصاص مییابد.
در نهایت x برابر با ۳، y برابر با [ 2, 3 ] میشود و در کنسول ابتدا "!F" و سپس "!G" چاپ میشود.
x[f()] = g()این عبارت نیز از چپ به راست ارزیابی میشود (با این فرض که متغیر x از قبل حاوی یک شیء است):
عبارت انتساب شروع میشود. دسترسی به ویژگیِ x[f()] در سمت چپ شروع به ارزیابی میکند و ابتدا خود متغیر x شناسایی میشود.
تابع f() اجرا شده، متن "!F" را چاپ میکند و به عدد ۲ تبدیل میشود.
ارزیابی دسترسی به ویژگی تمام شده و ارجاع دقیق به مشخصه مشخص میشود: x[2].
تابع g() اجرا شده، متن "!G" را چاپ میکند و به عدد ۳ تبدیل میشود.
عدد ۳ به x[2] اختصاص مییابد.
در نهایت مقدار ویژگی x[2] برابر با ۳ میشود و در کنسول متنهای "!F" و "!G" به ترتیب چاپ میشوند.
زنجیر کردن انتسابها یا تو در تو نوشتن آنها میتواند باعث رفتارهای عجیب شود. به همین دلیل، زنجیر کردن انتسابها در یک خط کد اصلاً توصیه نمیشود.
به طور خاص، قرار دادن یک زنجیره انتساب در دستورات تعریفی const ،let یا var معمولاً آنطور که انتظار دارید کار نمیکند. در این حالت، فقط بیرونیترین (چپترین) متغیر رسماً تعریف میشود و بقیه متغیرهای موجود در زنجیره، توسط آن دستور تعریف نخواهند شد:
const z = y = x = f();
این دستور در ظاهر به نظر میرسد که دارد هر سه متغیر x ،y و z را تعریف میکند؛ اما در واقع فقط متغیر z را تعریف میکند. متغیرهای y و x در حالت Strict Mode به عنوان ارجاع به متغیرهای ناموجود خطا میدهند و در حالت معمولی (Sloppy Mode)، به صورت پنهان متغیرهای سراسری (Global) ایجاد میکنند که اتفاق بدی است.
این محتوا کاملا رایگان توسط تیم کدلپر ترجمه شده و در اختیار شما کاربران عزیز قرار گرفته است، هر گونه کپی برداری برای مقاصد غیر رایگان و بدون ذکر منبع، مورد پیگیری قانونی قرار میگیرد.
ترجمه شده از منبع: https://developer.mozilla.org/en-US/docs/Web/JavaScript