Immutability فنکشنل پروگرامنگ میں ایک بنیادی اصول ہے، اور آبجیکٹ اورینٹڈ پروگراموں کو بھی بہت کچھ پیش کرنا ہے۔ ایک mutable آبجیکٹ ایک ایسا آبجیکٹ ہے جس کی حالت اسے بنانے کے بعد تبدیل کی جا سکتی ہے۔ ایک immutable آبجیکٹ ایک ایسا آبجیکٹ ہے جس کی حالت اسے بنانے کے بعد تبدیل نہیں کی جا سکتی۔
جاوا اسکرپٹ میں ایک immutable آبجیکٹ کی مثال کیا ہے؟
جاوا اسکرپٹ میں، کچھ بلٹ ان اقسام (نمبرز، سٹرنگز) immutable ہیں، لیکن کسٹم آبجیکٹ عام طور پر mutable ہوتے ہیں۔
کچھ بلٹ ان immutable جاوا اسکرپٹ آبجیکٹ Math، Date ہیں۔
یہاں سادہ جاوا اسکرپٹ آبجیکٹس پر immutability شامل کرنے/نقلی کرنے کے چند طریقے ہیں۔
آبجیکٹ مستقل خصوصیات
writable: false اور configurable: false کو ملا کر، آپ بنیادی طور پر ایک مستقل (تبدیل نہیں کیا جا سکتا، دوبارہ تعریف یا حذف نہیں کیا جا سکتا) ایک آبجیکٹ پراپرٹی کے طور پر بنا سکتے ہیں، جیسے:
let myObject = {};
Object.defineProperty(myObject, 'number', {
value: 42,
writable: false,
configurable: false,
});
console.log(myObject.number); // 42
myObject.number = 43;
console.log(myObject.number); // 42
توسیع سے روکیں
اگر آپ کسی آبجیکٹ کو نئی پراپرٹیز شامل کرنے سے روکنا چاہتے ہیں، لیکن آبجیکٹ کی باقی پراپرٹیز کو اکیلا چھوڑ دیں، تو Object.preventExtensions(...) کو کال کریں:
var myObject = {
a: 2,
};
Object.preventExtensions(myObject);
myObject.b = 3;
myObject.b; // undefined
نان-سٹرکٹ موڈ میں، b کی تخلیق خاموشی سے ناکام ہو جاتی ہے۔ سٹرکٹ موڈ میں، یہ ایک TypeError پھینکتا ہے۔
سیل
Object.seal() ایک 'سیل شدہ' آبجیکٹ بناتا ہے، جس کا مطلب ہے کہ یہ ایک موجودہ آبجیکٹ لیتا ہے اور بنیادی طور پر اس پر Object.preventExtensions() کو کال کرتا ہے، بلکہ اس کی تمام موجودہ پراپرٹیز کو بھی configurable: false کے طور پر نشان زد کرتا ہے۔
لہذا، نہ صرف آپ مزید پراپرٹیز شامل نہیں کر سکتے، بلکہ آپ کسی بھی موجودہ پراپرٹیز کو دوبارہ کنفیگر یا حذف بھی نہیں کر سکتے (اگرچہ آپ اب بھی ان کی قدروں کو تبدیل کر سکتے ہیں)۔
فریز
Object.freeze() ایک منجمد آبجیکٹ بناتا ہے، جس کا مطلب ہے کہ یہ ایک موجودہ آبجیکٹ لیتا ہے اور بنیادی طور پر اس پر Object.seal() کو کال کرتا ہے، بلکہ یہ تمام 'ڈیٹا ایکسیسر' پراپرٹیز کو بھی writable:false کے طور پر نشان زد کرتا ہے، تاکہ ان کی قدریں تبدیل نہ کی جا سکیں۔
یہ نقطہ نظر immutability کی اعلیٰ ترین سطح ہے جو آپ خود آبجیکٹ کے لیے حاصل کر سکتے ہیں، کیونکہ یہ آبجیکٹ یا اس کی کسی بھی براہ راست پراپرٹیز میں کسی بھی تبدیلی کو روکتا ہے (اگرچہ، جیسا کہ اوپر ذکر کیا گیا ہے، کسی بھی حوالہ شدہ دیگر آبجیکٹ کے مواد پر کوئی اثر نہیں پڑتا)۔
var immutable = Object.freeze({});
آبجیکٹ کو فریز کرنے سے نئی پراپرٹیز کو آبجیکٹ میں شامل کرنے کی اجازت نہیں ملتی اور موجودہ پراپرٹیز کو ہٹانے یا تبدیل کرنے سے روکتا ہے۔ Object.freeze() آبجیکٹ کی شمار، کنفیگر، رائٹ اور پروٹوٹائپ کو محفوظ رکھتا ہے۔ یہ پاس شدہ آبجیکٹ کو واپس کرتا ہے اور منجمد کاپی نہیں بناتا ہے۔
immutability کے کیا فوائد اور نقصانات ہیں؟
فوائد
- تبدیلی کا پتہ لگانا آسان - آبجیکٹ کی مساوات کو حوالہ جاتی مساوات کے ذریعے پرفارمنٹ اور آسان طریقے سے طے کیا جا سکتا ہے۔ یہ React اور Redux میں آبجیکٹ کے اختلافات کا موازنہ کرنے کے لیے مفید ہے۔
- immutable آبجیکٹس والے پروگراموں کے بارے میں سوچنا کم پیچیدہ ہوتا ہے، کیونکہ آپ کو یہ فکر کرنے کی ضرورت نہیں ہوتی کہ وقت کے ساتھ آبجیکٹ کیسے ترقی کر سکتا ہے۔
- فنکشنز سے immutable آبجیکٹس کو واپس کرتے یا پاس کرتے وقت ڈیفینسیو کاپیوں کی مزید ضرورت نہیں ہوتی، کیونکہ immutable آبجیکٹ کے ذریعے ترمیم کا کوئی امکان نہیں ہے۔
- حوالوں کے ذریعے آسان شیئرنگ - ایک آبجیکٹ کی ایک کاپی اتنی ہی اچھی ہے جتنی کوئی اور، لہذا آپ آبجیکٹس کو کیش کر سکتے ہیں یا ایک ہی آبجیکٹ کو کئی بار دوبارہ استعمال کر سکتے ہیں۔
- تھریڈ سیف - immutable آبجیکٹس کو کثیر تھریڈ والے ماحول میں تھریڈز کے درمیان محفوظ طریقے سے استعمال کیا جا سکتا ہے کیونکہ ان کے دیگر بیک وقت چلنے والے تھریڈز میں ترمیم ہونے کا کوئی خطرہ نہیں ہوتا ہے۔
- ImmutableJS جیسی لائبریریوں کا استعمال کرتے ہوئے، آبجیکٹ کو structural sharing کا استعمال کرتے ہوئے تبدیل کیا جاتا ہے اور اسی طرح کی ساخت کے ساتھ متعدد آبجیکٹ رکھنے کے لیے کم میموری کی ضرورت ہوتی ہے۔
نقصانات
- immutable ڈیٹا سٹرکچرز اور اس کے آپریشنز کی نادانستہ عملدرآمد کے نتیجے میں انتہائی خراب کارکردگی ہو سکتی ہے کیونکہ ہر بار نئے آبجیکٹ بنائے جاتے ہیں۔ موثر immutable ڈیٹا سٹرکچرز اور آپریشنز کے لیے لائبریریاں استعمال کرنے کی سفارش کی جاتی ہے جو structural sharing کا فائدہ اٹھاتے ہیں۔
- موجودہ آبجیکٹ کو تبدیل کرنے کے بجائے بہت سے چھوٹے آبجیکٹ کی تخصیص (اور تخصیص سے دستبرداری) کارکردگی پر اثر انداز ہو سکتی ہے۔ ایلوکیٹر یا گاربیج کلیکٹر کی پیچیدگی عام طور پر ہیپ پر موجود آبجیکٹس کی تعداد پر منحصر ہوتی ہے۔
- سائیکلک ڈیٹا سٹرکچرز جیسے گراف بنانا مشکل ہوتا ہے۔ اگر آپ کے پاس دو آبجیکٹ ہیں جنہیں انیشلائزیشن کے بعد تبدیل نہیں کیا جا سکتا، تو آپ انہیں ایک دوسرے کی طرف کیسے اشارہ کر سکتے ہیں؟
آپ اپنے کوڈ میں immutability کیسے حاصل کر سکتے ہیں؟
متبادل یہ ہے کہ const اعلانات کو تخلیق کے لیے اوپر ذکر کردہ تکنیکوں کے ساتھ مل کر استعمال کیا جائے۔ آبجیکٹس کو 'تبدیل' کرنے کے لیے، اصل آبجیکٹ کو تبدیل کرنے کے بجائے نئے آبجیکٹ بنانے کے لیے اسپریڈ آپریٹر، Object.assign، Array.concat() وغیرہ کا استعمال کریں۔
مثالیں:
// Array Example
const arr = [1, 2, 3];
const newArr = [...arr, 4]; // [1, 2, 3, 4]
// Object Example
const human = Object.freeze({ race: 'human' });
const john = { ...human, name: 'John' }; // {race: "human", name: "John"}
const alienJohn = { ...john, race: 'alien' }; // {race: "alien", name: "John"}