এটি কি ES6 এ কোনও বস্তুর ক্লোন করার ভাল উপায়?


155

"জাভাস্ক্রিপ্ট ক্লোন অবজেক্ট" এর জন্য গুগলিং কিছু সত্যই অদ্ভুত ফলাফল এনেছে, তাদের মধ্যে কিছু হতাশাই পুরানো এবং কিছুটি খুব জটিল, এটি ঠিক এতটা সহজ নয়:

let clone = {...original};

এতে কি কিছু ভুল আছে?


1
এটি আইনী ES6 নয়। তবে যদি এটি না থাকত তবে এটি কোনও ক্লোন নয়: আপনার ক্লোন এবং মূল বৈশিষ্ট্য উভয়ই এখন একই জিনিসগুলিকে নির্দেশ করে। উদাহরণস্বরূপ, original = { a: [1,2,3] }আপনাকে clone.aআক্ষরিক সাথে একটি ক্লোন দেয় original.a। উভয়ের মাধ্যমে পরিবর্তন cloneবা একই জিনিসটিoriginal পরিবর্তন করে , তাই না, এটি খারাপ =)
মাইক 'পোম্যাক্স' কামারম্যানস

2
@AlbertoRivera এটা এর ধরণ বৈধ জাভাস্ক্রিপ্ট, যে এটি একটি এর পর্যায় 2 প্রস্তাব জাভাস্ক্রিপ্ট মান ভবিষ্যতে উপরন্তু হওয়ার সম্ভাবনা যে।
ফ্রেক্সস্ট্রেম

@ ফ্রাক্সস্ট্রেম প্রশ্নটি ES6 সম্পর্কে হওয়ায় এটি জাভাস্ক্রিপ্ট বৈধ নয় =)
মাইক 'পোম্যাক্স' কামারম্যানস

3
অগভীর নাকি গভীর ক্লোনিং?
ফেলিক্স ক্লিং

2
আপনি ঠিক বলেছেন, এটি বৈধ ES6 নয়, এটি বৈধ ES9বিকাশকারী.মোজিলা.আর.ইন-
ইউএস

উত্তর:


240

এটি অগভীর ক্লোনিংয়ের জন্য ভাল । বস্তুর বিস্তার নাম ECMAScript 2018 এর একটি প্রমিত অংশ

গভীর ক্লোনিং জন্য আপনি একটি প্রয়োজন হবে বিভিন্ন সমাধান

const clone = {...original} অগভীর ক্লোন করতে

const newobj = {...original, prop: newOne} আসলভাবে মূলটিতে আরও একটি প্রোপ যুক্ত করতে এবং একটি নতুন অবজেক্ট হিসাবে সঞ্চয় করতে।


18
তবে, এটি কি কেবল অগভীর ক্লোন নয়? যেমন হিসাবে, সম্পত্তিগুলি পুনরাবৃত্তভাবে ক্লোন করা হয় না, তারা কি? সুতরাং, original.innerObject === clone.innerObject এবং original.innerObject.property পরিবর্তন করলে ক্লোন.আইন.অনবজেক্ট.প্রোপার্টি পরিবর্তন হবে।
মিলানিও

18
হ্যাঁ, এটি একটি অগভীর ক্লোন। আপনি যদি একটি গভীর ক্লোন চান তবে অবশ্যই ব্যবহার করতে হবেJSON.parse(JSON.stringify(input))
মার্ক শস্টটি এমএকাদেমি

8
/! \ JSON.parse (JSON.stringify (ইনপুট)) তারিখগুলি মিস করে, অপরিজ্ঞাত, ... এটি ক্লোনিংয়ের জন্য রূপালী বুলেট নয়! দেখুন: maxpou.fr/immutability-js-without-library
গিলিয়াম

1
তাহলে কী হ্যাক JSON.stringify () / JSON.parse () সত্যিই ES6 তে কোনও অবজেক্টের গভীর ক্লোন করার প্রস্তাবিত উপায়? আমি এটি প্রস্তাবিত দেখতে রাখা। ধকল।
সলভিটিগে

3
@ মার্কশাস্ট JSON.parse(JSON.stringify(input))কাজ করবে না, কারণ যদি সেখানে functionsবা infinityমান হিসাবে এটি কেবল nullতাদের জায়গায় নির্ধারিত হয়। এটি কেবল তখনই কাজ করবে যদি মানগুলি সহজ হয় literalsএবং না হয় functions
ব্যাকস্ল্যাশএন

65

সম্পাদনা: যখন এই উত্তর পোস্ট করা হয়েছিল, {...obj} বেশিরভাগ ব্রাউজারগুলিতে সিনট্যাক্স উপলব্ধ ছিল না। আজকাল, আপনি এটি ব্যবহার করে ভাল হওয়া উচিত (যদি না আপনি IE 11 সমর্থন করার প্রয়োজন হয়)।

অবজেক্ট.অ্যাসাইন ব্যবহার করুন।

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

var obj = { a: 1 };
var copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }

তবে এটি কোনও গভীর ক্লোন তৈরি করবে না। এখনও পর্যন্ত গভীর ক্লোনিংয়ের কোনও নেটিভ উপায় নেই।

সম্পাদনা: @ মাইক 'পোম্যাক্স' কমারম্যানরা মন্তব্যে উল্লিখিত হিসাবে আপনি ব্যবহার করে সাধারণ বস্তুগুলি (যেমন কোনও প্রোটোটাইপ, ফাংশন বা বিজ্ঞপ্তি সংক্রান্ত রেফারেন্স) গভীরভাবে ক্লোন করতে পারবেন JSON.parse(JSON.stringify(input))


19
সেখানে একটি রয়েছে, তবে আপনার অবজেক্টটি সত্যিকারের অবজেক্ট আক্ষরিক এবং খাঁটি ডেটা, JSON.parse(JSON.stringify(input))এক্ষেত্রে যথাযথ গভীর ক্লোন হয়। যাইহোক, মুহুর্তে প্রোটোটাইপস, ফাংশন বা বিজ্ঞপ্তি সংক্রান্ত রেফারেন্সগুলি কার্যকর হয়, সেই সমাধানটি আর কাজ করে না।
মাইক 'পোম্যাক্স' কামারম্যানস

@ মাইক'পোম্যাক্স 'কামারম্যানস এটি সত্য। গেটার এবং সেটটারদের জন্য কার্যকারিতা হারাতে ভয়ঙ্কর, যদিও ...
আলবার্তো রিভেরা

আপনার যদি কোনও বস্তু গভীরভাবে ক্লোন করতে জেনেরিক ফাংশন প্রয়োজন হয় তবে stackoverflow.com/a/13333781/560114 দেখুন
ম্যাট ব্রাউন

1
দেশীয়ভাবে গভীর ক্লোনিং করার এখন একটি উপায় রয়েছে ।
ড্যান ড্যাসক্লেস্কু

1
@ ড্যানডাসক্লেস্কু যদিও এটি পরীক্ষামূলক, এটি দেখতে বেশ আশাব্যঞ্জক। তথ্যের জন্য ধন্যবাদ!
আলবার্তো রিভেরা

4

আপনি যে পদ্ধতিগুলি ব্যবহার করেছেন সেগুলি যদি তারিখের মতো ডেটা ধরণের জড়িত অবজেক্টগুলির সাথে ভালভাবে কাজ না করে থাকে তবে এটি ব্যবহার করে দেখুন

আমদানি _

import * as _ from 'lodash';

গভীর ক্লোন অবজেক্ট

myObjCopy = _.cloneDeep(myObj);

শুধু import _ from 'lodash';যথেষ্ট। তবে "চাকাটি পুনরায় উদ্ভাবন করবেন না" এর জন্য +1।
rustyx

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

3

আপনি json.parse (json.stringify (অবজেক্ট)) ব্যবহার করতে না চাইলে আপনি পুনরাবৃত্তভাবে কী-মান কপি তৈরি করতে পারেন:

function copy(item){
  let result = null;
  if(!item) return result;
  if(Array.isArray(item)){
    result = [];
    item.forEach(element=>{
      result.push(copy(element));
    });
  }
  else if(item instanceof Object && !(item instanceof Function)){ 
    result = {};
    for(let key in item){
      if(key){
        result[key] = copy(item[key]);
      }
    }
  }
  return result || item;
}

তবে সর্বোত্তম উপায় হ'ল এমন ক্লাস তৈরি করা যা এটির নিজের ক্লোনটি ফেরত দিতে পারে

class MyClass{
    data = null;
    constructor(values){ this.data = values }
    toString(){ console.log("MyClass: "+this.data.toString(;) }
    remove(id){ this.data = data.filter(d=>d.id!==id) }
    clone(){ return new MyClass(this.data) }
}

2

@ মার্সেলের উত্তর অনুসরণ করে আমি দেখতে পেলাম ক্লোন করা বস্তুটিতে কিছু ফাংশন এখনও অনুপস্থিত ছিল। যেমন

function MyObject() {
  var methodAValue = null,
      methodBValue = null

  Object.defineProperty(this, "methodA", {
    get: function() { return methodAValue; },
    set: function(value) {
      methodAValue = value || {};
    },
    enumerable: true
  });

  Object.defineProperty(this, "methodB", {
    get: function() { return methodAValue; },
    set: function(value) {
      methodAValue = value || {};
    }
  });
}

যেখানে মাইওবজেক্টে আমি পদ্ধতি ক্লোন করতে পেরেছিলাম তবে পদ্ধতি বি বাদ দেওয়া হয়েছিল। এটি অনুপস্থিত কারণ এটি ঘটেছে

enumerable: true

যার অর্থ এটি প্রদর্শিত হয়নি

for(let key in item)

পরিবর্তে আমি স্যুইচ করা

Object.getOwnPropertyNames(item).forEach((key) => {
    ....
  });

যার মধ্যে অগণিত কীগুলি অন্তর্ভুক্ত থাকবে।

আমি আরও দেখতে পেলাম যে প্রোটোটাইপ ( প্রোটো ) ক্লোন করা হয়নি। তার জন্য আমি ব্যবহার শেষ করেছি

if (obj.__proto__) {
  copy.__proto__ = Object.assign(Object.create(Object.getPrototypeOf(obj)), obj);
}

পিএস: হতাশাজনক যে আমি এটি করার জন্য কোনও বিল্ট ইন ফাংশনটি খুঁজে পাইনি।


1

আপনি এটি এর মতো করেও করতে পারেন,

let copiedData = JSON.parse(JSON.stringify(data));

-1
We can do that with two way:
1- First create a new object and replicate the structure of the existing one by iterating 
 over its properties and copying them on the primitive level.

let user = {
     name: "John",
     age: 30
    };

    let clone = {}; // the new empty object

    // let's copy all user properties into it
    for (let key in user) {
      clone[key] = user[key];
    }

    // now clone is a fully independant clone
    clone.name = "Pete"; // changed the data in it

    alert( user.name ); // still John in the original object

2- Second we can use the method Object.assign for that 
    let user = { name: "John" };
    let permissions1 = { canView: true };
    let permissions2 = { canEdit: true };

    // copies all properties from permissions1 and permissions2 into user
    Object.assign(user, permissions1, permissions2);

  -Another example

    let user = {
      name: "John",
      age: 30
    };

    let clone = Object.assign({}, user);
It copies all properties of user into the empty object and returns it. Actually, the same as the loop, but shorter.

তবে অবজেক্ট.সেসাইন () কোনও গভীর ক্লোন তৈরি করে না

let user = {
  name: "John",
  sizes: {
    height: 182,
    width: 50
  }
};

let clone = Object.assign({}, user);

alert( user.sizes === clone.sizes ); // true, same object

// user and clone share sizes
user.sizes.width++;       // change a property from one place
alert(clone.sizes.width); // 51, see the result from the other one

এটি ঠিক করার জন্য, আমাদের ক্লোনিং লুপটি ব্যবহার করা উচিত যা ব্যবহারকারীর [কী] এর প্রতিটি মান পরীক্ষা করে এবং যদি এটি কোনও বস্তু হয়, তবে তার কাঠামোটিও প্রতিলিপি করুন। একে বলা হয় “গভীর ক্লোনিং”।

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


-1

উপরের সমস্ত পদ্ধতিতে বস্তুর গভীর ক্লোনিং পরিচালনা করে না যেখানে এটি n স্তরে নেস্টেড থাকে। আমি অন্যের চেয়ে এর পারফরম্যান্সটি পরীক্ষা করে দেখিনি তবে এটি সংক্ষিপ্ত এবং সহজ।

নীচের প্রথম উদাহরণে Object.assignঠিক প্রথম স্তর পর্যন্ত কোন ক্লোন ব্যবহার করে অবজেক্ট ক্লোনিং দেখানো হয়েছে ।

var person = {
    name:'saksham',
    age:22,
    skills: {
        lang:'javascript',
        experience:5
    }
}

newPerson = Object.assign({},person);
newPerson.skills.lang = 'angular';
console.log(newPerson.skills.lang); //logs Angular

নীচের পদ্ধতির গভীর ক্লোনের অবজেক্ট ব্যবহার করা

var person = {
    name:'saksham',
    age:22,
    skills: {
        lang:'javascript',
        experience:5
    }
}

anotherNewPerson = JSON.parse(JSON.stringify(person));
anotherNewPerson.skills.lang = 'angular';
console.log(person.skills.lang); //logs javascript


JSON.parse / স্ট্রিংফাই বছরের পর বছর ধরে একটি দরিদ্র গভীর ক্লোনিং পদ্ধতি হিসাবে উল্লেখ করা হচ্ছে । পূর্ববর্তী উত্তরগুলি, পাশাপাশি সম্পর্কিত প্রশ্নগুলি দয়া করে চেক করুন। এছাড়াও, এটি ES6-তে নতুন নয়।
ড্যান ড্যাসক্লেস্কু

@ ড্যানডাসকলেস্কু আমি এটি জানি এবং আমি মনে করি এটি সাধারণ বিষয়গুলির জন্য এটি ব্যবহার করার কোনও সমস্যা হওয়া উচিত নয়। অন্যরা একই পোস্টে এবং এমনকি মন্তব্য হিসাবে তাদের উত্তরগুলিতে এটি উল্লেখ করেছেন। আমি মনে করি এটি ডাউন ডাউনের প্রাপ্য নয়।
দক্ষম

ঠিক - "অন্যান্যরাও তাদের জবাবগুলিতে" JSON.parse / স্ট্রিংফাই উল্লেখ করেছে। একই সমাধান সহ আরও একটি উত্তর কেন পোস্ট করবেন?
ড্যান ড্যাসক্লেস্কু
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.