স্ট্রাকচার্ডক্লোন ব্যবহার করে জাভাস্ক্রিপ্টে ডিপ-কপি করা

প্ল্যাটফর্মটি এখন স্ট্রাকচারডক্লোন() দিয়ে পাঠানো হয়, যা গভীর-কপি করার জন্য একটি অন্তর্নির্মিত ফাংশন।

দীর্ঘতম সময়ের জন্য, একটি জাভাস্ক্রিপ্ট মানের একটি গভীর অনুলিপি তৈরি করতে আপনাকে কর্মক্ষেত্র এবং লাইব্রেরিগুলি অবলম্বন করতে হয়েছিল৷ প্ল্যাটফর্মটি এখন structuredClone() দিয়ে পাঠানো হয়, যা গভীর-কপি করার জন্য একটি অন্তর্নির্মিত ফাংশন।

ব্রাউজার সমর্থন

  • ক্রোম: 98।
  • প্রান্ত: 98।
  • ফায়ারফক্স: 94।
  • সাফারি: 15.4.

উৎস

জাভাস্ক্রিপ্টে একটি মান অনুলিপি করা প্রায় সবসময় অগভীর হয়, গভীরের বিপরীতে। এর মানে হল যে গভীরভাবে নেস্টেড মানগুলির পরিবর্তনগুলি কপির পাশাপাশি আসলটিতে দৃশ্যমান হবে৷

অবজেক্ট স্প্রেড অপারেটর ব্যবহার করে জাভাস্ক্রিপ্টে একটি অগভীর অনুলিপি তৈরি করার একটি উপায় ... :

const myOriginal = {
  someProp: "with a string value",
  anotherProp: {
    withAnotherProp: 1,
    andAnotherProp: true
  }
};

const myShallowCopy = {...myOriginal};

অগভীর অনুলিপিতে সরাসরি একটি সম্পত্তি যোগ করা বা পরিবর্তন করা শুধুমাত্র অনুলিপিকে প্রভাবিত করবে, আসল নয়:

myShallowCopy.aNewProp = "a new value";
console.log(myOriginal.aNewProp)
// ^ logs `undefined`

যাইহোক, একটি গভীরভাবে নেস্টেড সম্পত্তি যোগ করা বা পরিবর্তন করা কপি এবং আসল উভয়কেই প্রভাবিত করে:

myShallowCopy.anotherProp.aNewProp = "a new value";
console.log(myOriginal.anotherProp.aNewProp) 
// ^ logs `a new value`

অভিব্যক্তি {...myOriginal} স্প্রেড অপারেটর ব্যবহার করে myOriginal এর (গণনাযোগ্য) বৈশিষ্ট্যগুলির উপর পুনরাবৃত্তি করে। এটি সম্পত্তির নাম এবং মান ব্যবহার করে এবং একটি নতুনভাবে তৈরি, খালি বস্তুতে সেগুলিকে একের পর এক বরাদ্দ করে। যেমন, ফলস্বরূপ বস্তুটি আকৃতিতে অভিন্ন, তবে বৈশিষ্ট্য এবং মানের তালিকার নিজস্ব অনুলিপি সহ। মানগুলিও অনুলিপি করা হয়, কিন্তু তথাকথিত আদিম মানগুলি অ-আদিম মানের তুলনায় জাভাস্ক্রিপ্ট মান দ্বারা ভিন্নভাবে পরিচালনা করা হয়। MDN উদ্ধৃত করতে:

জাভাস্ক্রিপ্টে, একটি আদিম (আদিম মান, আদিম ডেটা টাইপ) হল এমন ডেটা যা কোনও বস্তু নয় এবং এর কোনও পদ্ধতি নেই। সাতটি আদিম ডেটা প্রকার রয়েছে: স্ট্রিং, সংখ্যা, বিগইন্ট, বুলিয়ান, অনির্ধারিত, প্রতীক এবং নাল।

MDN — আদিম

নন-প্রিমিটিভ মানগুলিকে রেফারেন্স হিসাবে পরিচালনা করা হয়, যার অর্থ হল মানটি অনুলিপি করার কাজটি সত্যিই একই অন্তর্নিহিত বস্তুর একটি রেফারেন্স অনুলিপি করা, যার ফলে অগভীর অনুলিপি আচরণ হয়।

গভীর অনুলিপি

একটি অগভীর অনুলিপির বিপরীত একটি গভীর অনুলিপি। একটি গভীর অনুলিপি অ্যালগরিদমও একটি বস্তুর বৈশিষ্ট্যগুলি একের পর এক অনুলিপি করে, কিন্তু যখন এটি অন্য বস্তুর একটি রেফারেন্স খুঁজে পায় তখন সেই বস্তুর একটি অনুলিপিও তৈরি করে। কোডের দুটি টুকরা ঘটনাক্রমে একটি বস্তুকে ভাগ করে না এবং অজান্তে একে অপরের অবস্থাকে ম্যানিপুলেট করে তা নিশ্চিত করার জন্য এটি খুবই গুরুত্বপূর্ণ হতে পারে।

জাভাস্ক্রিপ্টে একটি মানের গভীর-কপি তৈরি করার কোন সহজ বা সুন্দর উপায় ছিল না। অনেক লোক লোডাশের cloneDeep() ফাংশনের মতো তৃতীয় পক্ষের লাইব্রেরির উপর নির্ভর করে। যুক্তিযুক্তভাবে এই সমস্যার সবচেয়ে সাধারণ সমাধান ছিল একটি JSON-ভিত্তিক হ্যাক:

const myDeepCopy = JSON.parse(JSON.stringify(myOriginal));

প্রকৃতপক্ষে, এটি এমন একটি জনপ্রিয় সমাধান ছিল, যে V8 আক্রমনাত্মকভাবে JSON.parse() এবং বিশেষ করে উপরের প্যাটার্নটিকে যত দ্রুত সম্ভব অপ্টিমাইজ করেছে। এবং যখন এটি দ্রুত হয়, এটি কয়েকটি ত্রুটি এবং ট্রিপওয়ারের সাথে আসে:

  • রিকার্সিভ ডাটা স্ট্রাকচার : JSON.stringify() থ্রো করবে যখন আপনি এটাকে রিকারসিভ ডাটা স্ট্রাকচার দিবেন। লিঙ্ক করা তালিকা বা গাছের সাথে কাজ করার সময় এটি বেশ সহজে ঘটতে পারে।
  • অন্তর্নির্মিত প্রকারগুলি : Map , Set , Date , RegExp বা ArrayBuffer এর মতো অন্যান্য JS বিল্ট-ইন থাকলে JSON.stringify() নিক্ষেপ করবে।
  • ফাংশন : JSON.stringify() শান্তভাবে ফাংশন বাতিল করবে।

স্ট্রাকচার্ড ক্লোনিং

প্ল্যাটফর্মটির ইতিমধ্যে কয়েকটি জায়গায় জাভাস্ক্রিপ্ট মানগুলির গভীর অনুলিপি তৈরি করার ক্ষমতা প্রয়োজন: IndexedDB-তে একটি JS মান সংরক্ষণ করার জন্য কিছু ধরণের সিরিয়ালাইজেশন প্রয়োজন যাতে এটি ডিস্কে সংরক্ষণ করা যায় এবং পরে JS মান পুনরুদ্ধার করতে ডিসিরিয়ালাইজ করা যায়। একইভাবে, postMessage() এর মাধ্যমে একটি ওয়েবওয়ার্কারকে বার্তা পাঠানোর জন্য একটি JS মান একটি JS রাজ্য থেকে অন্য JS অঞ্চলে স্থানান্তর করা প্রয়োজন। এটির জন্য যে অ্যালগরিদম ব্যবহার করা হয় তাকে "স্ট্রাকচার্ড ক্লোন" বলা হয়, এবং সম্প্রতি পর্যন্ত, বিকাশকারীদের কাছে সহজে অ্যাক্সেসযোগ্য ছিল না।

সেটা এখন বদলে গেছে! HTML স্পেকটি সংশোধিত হয়েছে structuredClone() নামক একটি ফাংশনকে প্রকাশ করার জন্য যা ঠিক সেই অ্যালগরিদমটি চালায় যা ডেভেলপারদের সহজে জাভাস্ক্রিপ্ট মানগুলির গভীর অনুলিপি তৈরি করার উপায় হিসাবে।

const myDeepCopy = structuredClone(myOriginal);

তাই তো! যে সমগ্র API. আপনি যদি বিস্তারিত আরও গভীরে যেতে চান, MDN নিবন্ধটি একবার দেখুন।

বৈশিষ্ট্য এবং সীমাবদ্ধতা

স্ট্রাকচার্ড ক্লোনিং JSON.stringify() কৌশলের অনেকগুলি (যদিও সব নয়) ত্রুটিগুলি সমাধান করে। স্ট্রাকচার্ড ক্লোনিং চক্রীয় ডেটা স্ট্রাকচারগুলি পরিচালনা করতে পারে, অনেকগুলি অন্তর্নির্মিত ডেটা প্রকারগুলিকে সমর্থন করতে পারে এবং সাধারণত আরও শক্তিশালী এবং প্রায়শই দ্রুত হয়।

যাইহোক, এর এখনও কিছু সীমাবদ্ধতা রয়েছে যা আপনাকে অফ-গার্ড ধরতে পারে:

  • প্রোটোটাইপস : আপনি যদি একটি ক্লাস ইনস্ট্যান্সের সাথে structuredClone() ব্যবহার করেন, তাহলে আপনি রিটার্ন মান হিসাবে একটি প্লেইন অবজেক্ট পাবেন, কারণ স্ট্রাকচার্ড ক্লোনিং অবজেক্টের প্রোটোটাইপ চেইনকে বাতিল করে দেয়।
  • ফাংশন : যদি আপনার অবজেক্টে ফাংশন থাকে, structuredClone() একটি DataCloneError ব্যতিক্রম নিক্ষেপ করবে।
  • নন-ক্লোনযোগ্য : কিছু মান কাঠামোবদ্ধ ক্লোনযোগ্য নয়, বিশেষত Error এবং DOM নোড। এটি structuredClone() নিক্ষেপের কারণ হবে।

যদি এই সীমাবদ্ধতাগুলির মধ্যে কোনওটি আপনার ব্যবহারের ক্ষেত্রে একটি চুক্তি-ব্রেকার হয়, লোড্যাশের মতো লাইব্রেরিগুলি এখনও অন্যান্য গভীর-ক্লোনিং অ্যালগরিদমগুলির কাস্টম বাস্তবায়ন প্রদান করে যা আপনার ব্যবহারের ক্ষেত্রে উপযুক্ত হতে পারে বা নাও পারে৷

কর্মক্ষমতা

যদিও আমি একটি নতুন মাইক্রো-বেঞ্চমার্ক তুলনা করিনি, আমি 2018 এর প্রথম দিকে একটি তুলনা করেছিলাম , structuredClone() প্রকাশের আগে। তখন, JSON.parse() খুব ছোট বস্তুর জন্য দ্রুততম বিকল্প ছিল। আমি আশা করি যে এটি একই থাকবে। স্ট্রাকচার্ড ক্লোনিংয়ের উপর নির্ভরশীল কৌশলগুলি বড় বস্তুর জন্য (উল্লেখযোগ্যভাবে) দ্রুততর ছিল। নতুন structuredClone() অন্যান্য API-এর অপব্যবহার করার ওভারহেড ছাড়াই আসে এবং JSON.parse() এর চেয়ে আরও শক্তিশালী, আমি আপনাকে ডিপ কপি তৈরি করার জন্য এটিকে আপনার ডিফল্ট পদ্ধতির করার পরামর্শ দিচ্ছি।

উপসংহার

আপনি যদি JS-এ একটি মানের একটি গভীর-কপি তৈরি করতে চান—হয়ত আপনি অপরিবর্তনীয় ডেটা স্ট্রাকচার ব্যবহার করেন বা আপনি নিশ্চিত করতে চান যে কোনো ফাংশন আসলটিকে প্রভাবিত না করেই কোনো বস্তুকে ম্যানিপুলেট করতে পারে—আপনাকে আর সমাধানের জন্য পৌঁছাতে হবে না বা লাইব্রেরি JS ইকোসিস্টেমে এখন structuredClone() আছে। হুজ্জাহ।