ইন্টারনেটে বেশিরভাগ সমাধান নিয়ে বেশ কয়েকটি সমস্যা রয়েছে। সুতরাং আমি একটি ফলোআপ করার সিদ্ধান্ত নিয়েছি, যার মধ্যে রয়েছে, কেন গৃহীত উত্তরটি গ্রহণ করা উচিত নয়।
শুরুর অবস্থা
আমি একটি জাভাস্ক্রিপ্ট এর সমস্ত শিশু এবং তাদের বাচ্চাদের ইত্যাদির সাথে অনুলিপি করতে চাই Object
। কিন্তু যেহেতু আমি একটি স্বাভাবিক ডেভেলপার ধরনের নই, আমার Object
হয়ে গেছে স্বাভাবিক properties
, circular structures
এবং এমনকি nested objects
।
সুতরাং আসুন একটি circular structure
এবং nested object
প্রথম তৈরি করুন ।
function Circ() {
this.me = this;
}
function Nested(y) {
this.y = y;
}
আসুন একটি Object
নাম দিয়ে সব একত্রিত করা যাক a
।
var a = {
x: 'a',
circ: new Circ(),
nested: new Nested('a')
};
এর পরে, আমরা a
নামের একটি ভেরিয়েবলের অনুলিপি করতে b
এবং এটি পরিবর্তন করতে চাই।
var b = a;
b.x = 'b';
b.nested.y = 'b';
আপনি জানেন এখানে কী ঘটেছিল কারণ যদি না হয় তবে আপনি এই দুর্দান্ত প্রশ্নে অবতীর্ণ হন না।
console.log(a, b);
a --> Object {
x: "b",
circ: Circ {
me: Circ { ... }
},
nested: Nested {
y: "b"
}
}
b --> Object {
x: "b",
circ: Circ {
me: Circ { ... }
},
nested: Nested {
y: "b"
}
}
এখন একটি সমাধান খুঁজে বের করা যাক।
তাদেরকে JSON
আমি প্রথম চেষ্টাটি ব্যবহার করেছিলাম JSON
।
var b = JSON.parse( JSON.stringify( a ) );
b.x = 'b';
b.nested.y = 'b';
এটিতে খুব বেশি সময় নষ্ট করবেন না, আপনি পাবেন TypeError: Converting circular structure to JSON
।
পুনরাবৃত্তির অনুলিপি (স্বীকৃত "উত্তর")
আসুন গৃহীত উত্তরটি একবার দেখুন।
function cloneSO(obj) {
// Handle the 3 simple types, and null or undefined
if (null == obj || "object" != typeof obj) return obj;
// Handle Date
if (obj instanceof Date) {
var copy = new Date();
copy.setTime(obj.getTime());
return copy;
}
// Handle Array
if (obj instanceof Array) {
var copy = [];
for (var i = 0, len = obj.length; i < len; i++) {
copy[i] = cloneSO(obj[i]);
}
return copy;
}
// Handle Object
if (obj instanceof Object) {
var copy = {};
for (var attr in obj) {
if (obj.hasOwnProperty(attr)) copy[attr] = cloneSO(obj[attr]);
}
return copy;
}
throw new Error("Unable to copy obj! Its type isn't supported.");
}
ভাল লাগছে, হি? এটি অবজেক্টের পুনরাবৃত্তির অনুলিপি এবং অন্যান্য ধরণের হ্যান্ডলগুলিও পছন্দ করে Date
, তবে এটি কোনও প্রয়োজন ছিল না।
var b = cloneSO(a);
b.x = 'b';
b.nested.y = 'b';
পুনরাবৃত্তি এবং circular structures
একসাথে ভাল কাজ করে না ...RangeError: Maximum call stack size exceeded
নেটিভ সমাধান
আমার সহকর্মীর সাথে তর্ক করার পরে, আমার বস আমাদের জিজ্ঞাসা করলেন কী ঘটেছে, এবং কিছুটা গুগল করার পরে তিনি একটি সহজ সমাধান পেয়েছিলেন । এটি বলা হয় Object.create
।
var b = Object.create(a);
b.x = 'b';
b.nested.y = 'b';
কিছু সময় আগে এই সমাধানটি জাভাস্ক্রিপ্টে যুক্ত হয়েছিল এবং হ্যান্ডেলগুলিও circular structure
।
console.log(a, b);
a --> Object {
x: "a",
circ: Circ {
me: Circ { ... }
},
nested: Nested {
y: "b"
}
}
b --> Object {
x: "b",
circ: Circ {
me: Circ { ... }
},
nested: Nested {
y: "b"
}
}
... এবং আপনি দেখুন, এটি নেস্টেড কাঠামোর সাথে কাজ করে নি।
স্থানীয় সমাধানের জন্য পলিফিল
Object.create
আইই ৮ এর মতো পুরানো ব্রাউজারে একটি পলিফিল রয়েছে এটি মজিলার দ্বারা প্রস্তাবিত মতো কিছু এবং অবশ্যই এটি নিখুঁত নয় এবং দেশীয় সমাধান হিসাবে একই সমস্যার ফলস্বরূপ ।
function F() {};
function clonePF(o) {
F.prototype = o;
return new F();
}
var b = clonePF(a);
b.x = 'b';
b.nested.y = 'b';
আমি F
সুযোগের বাইরে রেখেছি যাতে আমাদের কী instanceof
বলছে তা আমাদের একবার দেখতে পারা যায় ।
console.log(a, b);
a --> Object {
x: "a",
circ: Circ {
me: Circ { ... }
},
nested: Nested {
y: "b"
}
}
b --> F {
x: "b",
circ: Circ {
me: Circ { ... }
},
nested: Nested {
y: "b"
}
}
console.log(typeof a, typeof b);
a --> object
b --> object
console.log(a instanceof Object, b instanceof Object);
a --> true
b --> true
console.log(a instanceof F, b instanceof F);
a --> false
b --> true
দেশীয় সমাধান হিসাবে একই সমস্যা , তবে কিছুটা খারাপ ফলাফল।
ভাল (তবে নিখুঁত নয়) সমাধান
চারপাশে খনন করার সময়, আমি একটি অনুরূপ প্রশ্ন পেয়েছি ( জাভাস্ক্রিপ্টে, যখন একটি গভীর অনুলিপি সম্পাদন করা হচ্ছে, তবে আমি কোনও চক্রকে কীভাবে এড়িয়ে চলব, কোনও সম্পত্তির কারণে "এই"? ) থাকার কারণে , তবে এটির আরও ভাল সমাধান সহ।
function cloneDR(o) {
const gdcc = "__getDeepCircularCopy__";
if (o !== Object(o)) {
return o; // primitive value
}
var set = gdcc in o,
cache = o[gdcc],
result;
if (set && typeof cache == "function") {
return cache();
}
// else
o[gdcc] = function() { return result; }; // overwrite
if (o instanceof Array) {
result = [];
for (var i=0; i<o.length; i++) {
result[i] = cloneDR(o[i]);
}
} else {
result = {};
for (var prop in o)
if (prop != gdcc)
result[prop] = cloneDR(o[prop]);
else if (set)
result[prop] = cloneDR(cache);
}
if (set) {
o[gdcc] = cache; // reset
} else {
delete o[gdcc]; // unset again
}
return result;
}
var b = cloneDR(a);
b.x = 'b';
b.nested.y = 'b';
এবং এর আউটপুট এক নজরে ...
console.log(a, b);
a --> Object {
x: "a",
circ: Object {
me: Object { ... }
},
nested: Object {
y: "a"
}
}
b --> Object {
x: "b",
circ: Object {
me: Object { ... }
},
nested: Object {
y: "b"
}
}
console.log(typeof a, typeof b);
a --> object
b --> object
console.log(a instanceof Object, b instanceof Object);
a --> true
b --> true
console.log(a instanceof F, b instanceof F);
a --> false
b --> false
প্রয়োজনীয়তা মেলানো হয়, কিন্তু এখনও কিছু ছোট বিষয়, পরিবর্তন সহ instance
এর nested
এবং circ
করতে Object
।
একটি পাতা ভাগ করে এমন গাছের কাঠামো অনুলিপি করা হবে না, তারা দুটি স্বতন্ত্র পাতাতে পরিণত হবে:
[Object] [Object]
/ \ / \
/ \ / \
|/_ _\| |/_ _\|
[Object] [Object] ===> [Object] [Object]
\ / | |
\ / | |
_\| |/_ \|/ \|/
[Object] [Object] [Object]
উপসংহার
পুনরাবৃত্তি এবং ক্যাশে ব্যবহারের সর্বশেষ সমাধানটি সেরা নাও হতে পারে তবে এটি অবজেক্টের সত্যিকারের গভীর অনুলিপি। এটি সহজ পরিচালনা করে properties
, circular structures
এবং nested object
, তবে ক্লোনিং করার সময় এটির উদাহরণটি বিশৃঙ্খলা করবে।
jsfiddle