Skip to content

Commit 2898ed4

Browse files
committed
Object Copying, References
1 parent d8387fe commit 2898ed4

File tree

17 files changed

+236
-0
lines changed

17 files changed

+236
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,230 @@
1+
# অবজেক্ট কপি করা, রেফেরেন্স
2+
3+
অবজেক্ট এবং প্রিমিটিভ দের মধ্যে অন্যতম পার্থক্য হলো যে অবজেক্ট গুলি কপি ও সংরখ্যন হয় রেফারেন্স এর মাধ্যমে ।
4+
5+
6+
প্রিমিটিভ মান: স্ট্রিং, সংখ্যা, বুলিয়ানস - "সম্পূর্ণ মান হিসাবে" এসাইন/কপি করা হয়।
7+
8+
যেমন:
9+
10+
```js
11+
let message = "Hello!";
12+
let phrase = message;
13+
```
14+
15+
As a result we have two independent variables, each one is storing the string `"Hello!"`.
16+
এর ফলে আমরা দুটি স্বাধীন ভেরিয়েবল আছে, প্রতিটি "হেলো" স্ট্রিংটি সংরক্ষণ করছে ।
17+
18+
![](variable-copy-value.svg)
19+
20+
অবজেক্ট রা এমন নয়।
21+
22+
** একটি ভেরিএবল অবজেক্ট কে সংরক্ষণ করে না, বরং এর ঠিকানা সংরক্ষণ করে, অন্য কথায় এটির একটি "রেফারেন্স" *
23+
24+
অবজেক্ট এর ছবিঃ
25+
26+
```js
27+
let user = {
28+
name: "John"
29+
};
30+
```
31+
32+
![](variable-contains-reference.svg)
33+
34+
এখানে, বস্তুটি মেমোরির কোথাও সংরক্ষণ করা হয়েছে। এবং ভেরিয়েবল `user` এর কাছে এর রেফারেন্স আছে।
35+
36+
** যখন কোনও বস্তুর ভেরিয়েবল কপি করা হয় - রেফারেন্সটি কপি হয়, বস্তুটি নকল হয় না * **
37+
38+
যেমন :
39+
40+
```js no-beautify
41+
let user = { name: "John" };
42+
43+
let admin = user; // রেফারেন্স করই হলো
44+
```
45+
46+
এখন আমাদের দুটি ভেরিয়েবল রয়েছে, প্রত্যেকেই একই বস্তুর রেফারেন্স:
47+
48+
![](variable-copy-reference.svg)
49+
50+
আমরা এই দুটি ভেরিএবল এর যেকোনো টি ব্যাবহার করে অবজেক্ট টি এক্সেস করতে পারি ও এর ভেতরের কন্টেন্ট বা ডেটা গুলি পরিবর্তন করতে পারি।
51+
52+
```js run
53+
let user = { name: 'John' };
54+
55+
let admin = user;
56+
57+
*!*
58+
admin.name = 'Pete'; // এডমিন রেফারেন্সে এর মাদ্ধ্যমে পরিবর্তন হোল
59+
*/!*
60+
61+
alert(*!*user.name*/!*); // 'Pete', changes are seen from the "user" reference
62+
```
63+
64+
উপরের উদাহরণটি প্রমাণ করে যে এখানে কেবল একটি অবজেক্ট রয়েছে।যেন আমাদের একি কক্ষের দুটি চাবি আছে আর আমরা একটি চাবি (`admin`) দিয়ে কক্ষে প্রবেশ করেছি ও অন্যটি (`user`) দিয়ে কক্ষের ভেতরে উকি দিয়েছি।
65+
66+
## রেফারেন্স এর মাধ্যমে তুলনা
67+
68+
ইকুয়ালিটি `==` ও স্ট্রিক্ট ইকুয়ালিটি `===` দুটোই অবজেক্টের ক্ষেত্রে সমানভাবে কাজ করে।
69+
70+
**যদি দুটি অবজেক্ট একই বস্তু হয়, শুধুমাত্র তাহলেই তারা "ইকুয়াল" **
71+
72+
এখানে দুইটি ভেরিএবল একই অবজেক্ট কে রেফারেন্স করে, সুতরাং তারা ইকুয়াল:
73+
74+
```js run
75+
let a = {};
76+
let b = a; // রেফারেন্স কপি হোলো
77+
78+
alert( a == b ); // true, দুটি অবজেক্ট ই সমান
79+
alert( a === b ); // true
80+
```
81+
82+
আর এখানে দুটি অবজেক্ট সমান নয়, যদিও তারা দুজনই খালি :
83+
84+
```js run
85+
let a = {};
86+
let b = {}; // দুটি স্বাধীন অবজেক্ট
87+
88+
alert( a == b ); // false
89+
```
90+
91+
`obj1 > obj2` এর মত তুলনা এর জন্য or অথবা কোন প্রিমিটিভ এর সাথে তুলনা করার জন্য `obj == 5`, অবজেক্ট কে প্রিমিটিভ এ রূপান্তর করা হয়। অবজেক্ট গুলোকে কিভাবে তুলনা করা হয় তা সম্পর্কে আমরা শিগ্রই জানব, কিন্তু সত্যি বলতে এই ধরনের তুলনা খুব কমি করা হয়, সাধারণত ভুলক্রমে।
92+
93+
## ক্লোন করা ও মিলিত করা, Object.assign
94+
95+
তো আমরা জানলাম অবজেক্ট ভেরিএবল কে কপি করলে তা শুধু একটি নতুন রেফারেন্স তৈরি করে।
96+
97+
কিন্তু আমাদের যদি অবজেক্ট এর স্বাধীন নকল বা ক্লোন তৈরি করতে হয় তাহলে আমরা কই করব?
98+
99+
তাও সম্ভব কিন্তু একটু কঠিন, কারণ এই কাজ করার জন্য জাভাস্ক্রিপ্ট এর কোন অন্তর্নির্মিত মেথড নেই।
100+
আসলে এটি খুব কমই প্রয়োজন হয়। রেফারেন্সে কপি করাই বেশিরভাগ সময় যথেষ্ট।
101+
102+
কিন্তু আমরা যদি আসলেই এটি চাই তাহলে আমাদের নতুন একটি অবজেক্ট বানাতে হবে, ও মুল অবজেক্ট তির সম্পূর্ণ কাঠামো কে নকল করে এর সকল প্রপার্টির প্রিমিটিভ স্তরে প্রতিলিতি তৈরি করতে হবে।
103+
104+
যেমন:
105+
106+
```js run
107+
let user = {
108+
name: "John",
109+
age: 30
110+
};
111+
112+
*!*
113+
let clone = {}; // নতুন খালি অবজেক্ট
114+
115+
// এখন user অবজেক্ট এর সকল প্রপার্টি কে clone অবজেক্ট এ কপি করি
116+
for (let key in user) {
117+
clone[key] = user[key];
118+
}
119+
*/!*
120+
121+
122+
// এখন ক্লোন হচ্ছে একটি স্বাধীন অবজেক্ট যার কন্টেন্ট ইউজার এর সমান
123+
clone.name = "Pete"; // ডাটা পরিবর্তন করলাম
124+
125+
alert( user.name ); // মুল অবজেক্ট এ এখনো John
126+
```
127+
128+
আমরা এর জন্য [Object.assign](mdn:js/Object/assign) মেথড টিও ব্যাবহার করতে পারি।
129+
130+
এর সিনট্যাক্স হলো:
131+
132+
```js
133+
Object.assign(dest, [src1, src2, src3...])
134+
```
135+
136+
- প্রথম আর্গুমেন্ট `dest` হলো টার্গেট অবজেক্ট ।
137+
- বাকি আর্গুমেন্ট গুলো `src1, ..., srcN` (যতো প্রয়োজন দেয়া যাবে) হলো মুল অবজেক্ট।
138+
- এটি মুল অবজেক্ট এর সকল প্রপার্টি `src1, ..., srcN` টার্গেট `dest` এ কপি করে। অন্য কথায়, দ্বিতীয় আর্গুমেন্ট থেকে বাকি সকল আর্গুমেন্ট এর প্রপার্টি গুলো প্রথম অবজেক্ট এ কপি হয়।
139+
- এই কল টি `dest` কে রিটার্ন করে।
140+
141+
আমরা এটি ব্যাবহার করে একাধিক অবজেক্ট এ একটি অবজেক্ট এ মিলিত করতে পারে:
142+
```js
143+
let user = { name: "John" };
144+
145+
let permissions1 = { canView: true };
146+
let permissions2 = { canEdit: true };
147+
148+
*!*
149+
// copies all properties from permissions1 and permissions2 into user
150+
Object.assign(user, permissions1, permissions2);
151+
*/!*
152+
153+
// now user = { name: "John", canView: true, canEdit: true }
154+
```
155+
156+
কপি করা প্রপার্টি যদি ইতিমধ্যেই থেকে থাকে থাকলে এটি ওভাররাইট হয়ে যাবে:
157+
158+
```js run
159+
let user = { name: "John" };
160+
161+
Object.assign(user, { name: "Pete" });
162+
163+
alert(user.name); // now user = { name: "Pete" }
164+
```
165+
166+
আমরা `for..in` এর জায়গায় `Object.assign` ব্যাবহার করে সাধারণ ক্লোনিং করতে পারি :
167+
168+
```js
169+
let user = {
170+
name: "John",
171+
age: 30
172+
};
173+
174+
*!*
175+
let clone = Object.assign({}, user);
176+
*/!*
177+
```
178+
179+
এটি `user` এর সকল প্রপার্টি কে খালি অবজেক্ট এ কপি করে তাকে রিটার্ন করে ।
180+
181+
## অভ্যন্তরীণ ক্লোনিং (Nested cloning)
182+
183+
এতখ্যন পর্জন্ত আমরা ধরে নিয়েছিলাম যে `user` এর সকল প্রপার্টি ই প্রিমিটিভ । কিন্তু প্রপার্টি গুলো তো অন্যান্য অবজেক্ট এর রেফারেন্স ও হতে পারে । সেক্ষেত্রে আমরা কি করবো?
184+
185+
যেমন:
186+
```js run
187+
let user = {
188+
name: "John",
189+
sizes: {
190+
height: 182,
191+
width: 50
192+
}
193+
};
194+
195+
alert( user.sizes.height ); // 182
196+
```
197+
198+
এখন এটি `clone.sizes = user.sizes` কে কপি করার জন্য যথেষ্ট নয়, কারণ `user.sizes` হলো একটি অবজেক্ট, এটি রেফারেন্সের মাধ্যমে কপি হবে। সুতরাং `clone``user` একই size শেয়ার করবে:
199+
200+
এমন:
201+
202+
```js run
203+
let user = {
204+
name: "John",
205+
sizes: {
206+
height: 182,
207+
width: 50
208+
}
209+
};
210+
211+
let clone = Object.assign({}, user);
212+
213+
alert( user.sizes === clone.sizes ); // true, একই অবজেক্ট
214+
215+
// user এবং clone size কে শেয়ার করে
216+
user.sizes.width++; // একটি জায়গা থেকে প্রপার্টি পরিবর্তন
217+
alert(clone.sizes.width); // 51, অন্য জায়গায় রেসাল্ট দেখা
218+
```
219+
220+
এটি সমাধান করার জন্য আমাদের একটি ক্লোনিং লুপ ব্যাবহার করা লাগবে যা `user[key]` এর প্রত্যেক মান কে প্রিক্ষা করবে, এবং যদি এটি অবজেক্ট হয়, তাহলে এর স্ট্রাকচার কেও কপি করবে। একে বলে "ডিপ ক্লোনিং".
221+
222+
আমরা রিকার্সন ব্যাবহার করে এটি তৈরি করতে পারি অথবা ইতিমধ্যেই বাস্তবায়িত একটি ব্যাবহার করতে পারি, যেমন [lodash](https://lodash.com) এর [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep) ফাংশন।
223+
224+
## সংক্ষিপ্ত
225+
226+
অবজেক্ট গুলো রেফারেন্স এর মাধ্যমে কপি হয়। অন্য কথায়, একটি ভেরিয়েবল অবজেক্ট এর মান সংরক্ষণ করে না , বরং একটি রেফারেন্স (মেমোরি এড্রেস) সংরক্ষণ করে। সুতরাং এই ধরনের ভেরিয়েবল কে কপি করলে অবজেক্ট কপি হয় না বরং রেফারেন্স কপি হয়।
227+
228+
রেফারেন্সে এর মাধ্যমে করে সকল কাজ (যেমন প্রপার্টি যোগ করা/মোছা) একই অবজেক্ট এ সম্পাদিত হয়।
229+
230+
একটি "আসল কপি" (ক্লোন) তৈরি করতে আমরা ব্যাবহার করতে পারি `Object.assign` যাকে "শ্যালো কপি"(অভ্যন্তরীণ অবজেক্ট রেফারেন্সের মাধ্যমে কপি হয়) বলা হয় অথবা আমরা ব্যাবহার করতে পারি [_.cloneDeep(obj)](https://lodash.com/docs#cloneDeep) এর মত "ডিপ ক্লোনিং" ফাংশন।
Loading

0 commit comments

Comments
 (0)