স্প্রেড সিনট্যাক্সটি ব্যবহার করে ES6 এ গভীর অনুলিপি করুন


103

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

export const mapCopy = (object, callback) => {
    return Object.keys(object).reduce(function (output, key) {

    output[key] = callback.call(this, {...object[key]});

    return output;
    }, {});
}

এটি কাজ করে:

    return mapCopy(state, e => {

            if (e.id === action.id) {
                 e.title = 'new item';
            }

            return e;
        })

তবে এটি অভ্যন্তরীণ আইটেমগুলিকে গভীরভাবে অনুলিপি করে না তাই আমার এটির জন্য টুইট করতে হবে:

export const mapCopy = (object, callback) => {
    return Object.keys(object).reduce(function (output, key) {

    let newObject = {...object[key]};
    newObject.style = {...newObject.style};
    newObject.data = {...newObject.data};

    output[key] = callback.call(this, newObject);

    return output;
    }, {});
}

এটি কম মার্জিত হয় কারণ এটি জানতে যে কোন জিনিসগুলি পাস হয়েছে। ES6- তে কোনও অবজেক্টের গভীর অনুলিপি করতে স্প্রেড সিনট্যাক্স ব্যবহার করার কোনও উপায় আছে কি?



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

উত্তর:


73

ES6 এর মতো কোনও কার্যকারিতা অন্তর্নির্মিত নয়। আপনি কী করতে চান তার উপর নির্ভর করে আপনার কাছে কয়েকটি বিকল্প রয়েছে বলে আমি মনে করি।

আপনি যদি সত্যিই গভীর অনুলিপি করতে চান:

  1. একটি গ্রন্থাগার ব্যবহার করুন। উদাহরণস্বরূপ, লোড্যাশের একটি cloneDeepপদ্ধতি রয়েছে।
  2. আপনার নিজস্ব ক্লোনিং ফাংশনটি কার্যকর করুন।

আপনার নির্দিষ্ট সমস্যার বিকল্প সমাধান (কোনও গভীর অনুলিপি নেই)

তবে আমি মনে করি, আপনি যদি কয়েকটি জিনিস পরিবর্তন করতে ইচ্ছুক হন তবে আপনি নিজের কিছু কাজ বাঁচাতে পারেন। আমি ধরে নিচ্ছি যে আপনি আপনার ফাংশনে সমস্ত কল সাইট নিয়ন্ত্রণ করছেন।

  1. নির্দিষ্ট করুন যে সমস্ত কলব্যাকগুলি পাস করা হয়েছে mapCopyবিদ্যমান অবজেক্টটির পরিবর্তনের পরিবর্তে নতুন অবজেক্টগুলি ফিরিয়ে আনতে হবে। উদাহরণ স্বরূপ:

    mapCopy(state, e => {
      if (e.id === action.id) {
        return Object.assign({}, e, {
          title: 'new item'
        });
      } else {  
        return e;
      }
    });
    

    এটি Object.assignএকটি নতুন অবজেক্ট তৈরির জন্য ব্যবহার eকরে, সেই নতুন অবজেক্টের বৈশিষ্ট্য নির্ধারণ করে , তারপরে সেই নতুন অবজেক্টে একটি নতুন শিরোনাম সেট করে। এর অর্থ আপনি কখনই বিদ্যমান অবজেক্টগুলিকে পরিবর্তন করতে পারবেন না এবং যখন প্রয়োজন হয় কেবল তখনই নতুন তৈরি করেন।

  2. mapCopy এখন সত্যিই সহজ হতে পারে:

    export const mapCopy = (object, callback) => {
      return Object.keys(object).reduce(function (output, key) {
        output[key] = callback.call(this, object[key]);
        return output;
      }, {});
    }
    

মূলত, mapCopyতার কলকারীদের সঠিক কাজ করার জন্য বিশ্বাস করা হচ্ছে। এই কারণেই আমি বলেছিলাম এটি অনুমান করে আপনি সমস্ত কল সাইট নিয়ন্ত্রণ করেন।


4
অবজেক্ট.সেসাইন গভীরভাবে অনুলিপি করে না। বিকাশকারী.মোজিলা.অর্গ.ইন- ইউএস / ডকস / ওয়েবে / জাভা স্ক্রিপ্ট / রেফারেন্স / see দেখুন - অবজেক্ট.সেসাইন () সম্পত্তি মানগুলি অনুলিপি করে। "যদি উত্সের মানটি কোনও অবজেক্টের রেফারেন্স হয় তবে এটি কেবল সেই রেফারেন্স মানটিই অনুলিপি করে।"
গ্রেগ সোমারস

ঠিক। এটি একটি বিকল্প সমাধান যা গভীর অনুলিপি জড়িত না । আমি আমার উত্তরটি সে সম্পর্কে আরও স্পষ্ট হতে আপডেট করব।
ফ্রাঙ্ক ট্যান

105

পরিবর্তে গভীর অনুলিপি জন্য এটি ব্যবহার করুন

var newObject = JSON.parse(JSON.stringify(oldObject))

var oldObject = {
  name: 'A',
  address: {
    street: 'Station Road',
    city: 'Pune'
  }
}
var newObject = JSON.parse(JSON.stringify(oldObject));

newObject.address.city = 'Delhi';
console.log('newObject');
console.log(newObject);
console.log('oldObject');
console.log(oldObject);


65
এটি কেবল তখন কাজ করে যদি আপনার ফাংশনগুলি ক্লোন করার প্রয়োজন না হয়। JSON সমস্ত ফাংশন উপেক্ষা করবে যাতে আপনার ক্লোনটিতে তা না থাকে।
নোল্যান্ড

7
ফাংশনগুলি বাদ দিয়ে, আপনার এই পদ্ধতিটি ব্যবহার করে
অপরিজ্ঞাত

4
প্রোটোটাইপ চেইন সিরিয়ালযুক্ত না হওয়ায় আপনার কোনও ব্যবহারকারী-সংজ্ঞায়িত শ্রেণিতে সমস্যাও থাকবে।
প্যাট্রিক রবার্টস

9
আপনার সমাধান JSON সিরিয়ালাইজেশন ব্যবহার করে কিছু সমস্যা আছে। এটি করে আপনি কোনও জাভাস্ক্রিপ্ট সম্পত্তি হারাবেন যা ফাংশন বা ইনফিনিটির মতো জেএসএনে কোনও সমতুল্য টাইপ নেই। অপরিশোধিত হিসাবে নির্ধারিত যে কোনও সম্পত্তি JSON.stringify দ্বারা উপেক্ষা করা হবে, যার কারণে তারা ক্লোনযুক্ত বস্তুটিতে মিস হবে। এছাড়াও, কিছু বস্তু তারিখ, সেট, মানচিত্র এবং আরও অনেকের মতো স্ট্রিতে রূপান্তরিত হয়।
জোনাথন ব্রিজিও

4
আমার অবজেক্টগুলির একটি অ্যারের সত্যিকারের অনুলিপি তৈরি করার চেষ্টা করার একটি ভয়াবহ দুঃস্বপ্ন ছিল objects অবজেক্টগুলি যা মূলত ডেটা মান ছিল, কোনও ক্রিয়াকলাপ নয়। যদি আপনার চিন্তা করতে হয় তবে এই পদ্ধতিটি সুন্দরভাবে কাজ করে।
চার্লি

30

এমডিএন থেকে

দ্রষ্টব্য: একটি অ্যারে অনুলিপি করার সময় স্প্রেড সিনট্যাক্স কার্যকরভাবে এক স্তর পর্যন্ত যায়। অতএব, নিম্নলিখিত উদাহরণটি দেখায় যেমন এটি বহুমাত্রিক অ্যারেগুলি অনুলিপি করা অনুপযুক্ত হতে পারে (এটি অবজেক্ট.সেসাইন () এবং স্প্রেড সিনট্যাক্সের সাথে একই)।

ব্যক্তিগতভাবে, আমি লোডাসের ক্লোনডিপ ব্যবহার করার পরামর্শ দিচ্ছি মাল্টি-লেভেল অবজেক্ট / অ্যারে ক্লোনিংয়ের জন্য ফাংশনটি ।

এখানে একটি কার্যকারী উদাহরণ:

const arr1 = [{ 'a': 1 }];

const arr2 = [...arr1];

const arr3 = _.clone(arr1);

const arr4 = arr1.slice();

const arr5 = _.cloneDeep(arr1);

const arr6 = [...{...arr1}]; // a bit ugly syntax but it is working!


// first level
console.log(arr1 === arr2); // false
console.log(arr1 === arr3); // false
console.log(arr1 === arr4); // false
console.log(arr1 === arr5); // false
console.log(arr1 === arr6); // false

// second level
console.log(arr1[0] === arr2[0]); // true
console.log(arr1[0] === arr3[0]); // true
console.log(arr1[0] === arr4[0]); // true
console.log(arr1[0] === arr5[0]); // false
console.log(arr1[0] === arr6[0]); // false
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>


4
arr6 আমার জন্য কাজ করছে না। ব্রাউজারে (ক্রোম 59.0 যা ইএস 6 সমর্থন করে আমি আনকাটড সিনট্যাক্স এরিয়ারটি পেয়েছি: অপ্রত্যাশিত টোকেন ... এবং নোডে 8.9.3 যা ইএস 7 সমর্থন করে আমি টাইপ এরর পেয়েছি :
আচি ইভেন-দার

@ আচিএভেন-দার স্যার করবেন না কেন আপনি ত্রুটি পেয়েছেন? আপনি এই কোডটি সরাসরি নীল বোতাম টিপে স্ট্যাকওভারফ্লোতে Run code snippetচালাতে পারেন এবং এটি সঠিকভাবে চালানো উচিত।
মিনা লুক

4
arr6 আমার জন্য কাজ করে না। ব্রাউজারে - ক্রোম 65
ইয়াহোনাটান ইহেজেল

18

আমি প্রায়শই এটি ব্যবহার করি:

function deepCopy(obj) {
    if(typeof obj !== 'object' || obj === null) {
        return obj;
    }

    if(obj instanceof Date) {
        return new Date(obj.getTime());
    }

    if(obj instanceof Array) {
        return obj.reduce((arr, item, i) => {
            arr[i] = deepCopy(item);
            return arr;
        }, []);
    }

    if(obj instanceof Object) {
        return Object.keys(obj).reduce((newObj, key) => {
            newObj[key] = deepCopy(obj[key]);
            return newObj;
        }, {})
    }
}

3
const a = {
  foods: {
    dinner: 'Pasta'
  }
}
let b = JSON.parse(JSON.stringify(a))
b.foods.dinner = 'Soup'
console.log(b.foods.dinner) // Soup
console.log(a.foods.dinner) // Pasta

ব্যবহার JSON.stringifyএবং JSON.parseসেরা উপায়। কারণ স্প্রেড অপারেটরটি ব্যবহার করে আমরা যখন জসন অবজেক্টের ভিতরে অন্য একটি বস্তু থাকে তখন আমরা কার্যকর উত্তরটি পাই না। আমাদের এটি ম্যানুয়ালি নির্দিষ্ট করতে হবে।


1
function deepclone(obj) {
    let newObj = {};

    if (typeof obj === 'object') {
        for (let key in obj) {
            let property = obj[key],
                type = typeof property;
            switch (type) {
                case 'object':
                    if( Object.prototype.toString.call( property ) === '[object Array]' ) {
                        newObj[key] = [];
                        for (let item of property) {
                            newObj[key].push(this.deepclone(item))
                        }
                    } else {
                        newObj[key] = deepclone(property);
                    }
                    break;
                default:
                    newObj[key] = property;
                    break;

            }
        }
        return newObj
    } else {
        return obj;
    }
}

1
// use: clone( <thing to copy> ) returns <new copy>
// untested use at own risk
function clone(o, m){
  // return non object values
  if('object' !==typeof o) return o
  // m: a map of old refs to new object refs to stop recursion
  if('object' !==typeof m || null ===m) m =new WeakMap()
  var n =m.get(o)
  if('undefined' !==typeof n) return n
  // shallow/leaf clone object
  var c =Object.getPrototypeOf(o).constructor
  // TODO: specialize copies for expected built in types i.e. Date etc
  switch(c) {
    // shouldn't be copied, keep reference
    case Boolean:
    case Error:
    case Function:
    case Number:
    case Promise:
    case String:
    case Symbol:
    case WeakMap:
    case WeakSet:
      n =o
      break;
    // array like/collection objects
    case Array:
      m.set(o, n =o.slice(0))
      // recursive copy for child objects
      n.forEach(function(v,i){
        if('object' ===typeof v) n[i] =clone(v, m)
      });
      break;
    case ArrayBuffer:
      m.set(o, n =o.slice(0))
      break;
    case DataView:
      m.set(o, n =new (c)(clone(o.buffer, m), o.byteOffset, o.byteLength))
      break;
    case Map:
    case Set:
      m.set(o, n =new (c)(clone(Array.from(o.entries()), m)))
      break;
    case Int8Array:
    case Uint8Array:
    case Uint8ClampedArray:
    case Int16Array:
    case Uint16Array:
    case Int32Array:
    case Uint32Array:
    case Float32Array:
    case Float64Array:
      m.set(o, n =new (c)(clone(o.buffer, m), o.byteOffset, o.length))
      break;
    // use built in copy constructor
    case Date:
    case RegExp:
      m.set(o, n =new (c)(o))
      break;
    // fallback generic object copy
    default:
      m.set(o, n =Object.assign(new (c)(), o))
      // recursive copy for child objects
      for(c in n) if('object' ===typeof n[c]) n[c] =clone(n[c], m)
  }
  return n
}

মন্তব্যগুলি ব্যাখ্যাটির জন্য কোডটিতে রয়েছে।
Wookies- উইল-কোড

1
const cloneData = (dataArray) => {
    newData= []
    dataArray.forEach((value) => {
        newData.push({...value})
    })
    return newData
}
  • a = [{নাম: "সিভা"}, {নাম: "সিভা 1"}];
  • খ = আমারকপি (ক)
  • খ === এ // মিথ্যা `

1

আমি নিজেই গত দিন এই উত্তরগুলিতে অবতরণ করেছি, জটিল কাঠামোগুলি গভীরভাবে অনুলিপি করার একটি উপায় সন্ধান করার চেষ্টা করছি, যার মধ্যে পুনরাবৃত্ত লিঙ্কগুলি অন্তর্ভুক্ত থাকতে পারে। আগে যে কোনও প্রস্তাব দেওয়া থেকে আমি সন্তুষ্ট না হওয়ায় আমি নিজেই এই চাকাটি বাস্তবায়ন করেছি। এবং এটি বেশ ভাল কাজ করে। আশা করি এটি কাউকে সাহায্য করবে।

ব্যবহারের উদাহরণ:

OriginalStruct.deep_copy = deep_copy; // attach the function as a method

TheClone = OriginalStruct.deep_copy();

দয়া করে https://github.com/latitov/JS_DeepCopy দেখুনএটি কীভাবে ব্যবহার করতে হয় তার সরাসরি উদাহরণগুলির জন্য এবং এছাড়াও গভীর_প্রিন্ট () রয়েছে।

আপনার যদি এটির দ্রুত প্রয়োজন হয়, এই মুহুর্তে ডিপ_কপি () ফাংশনের উত্স:

function deep_copy() {
    'use strict';   // required for undef test of 'this' below

    // Copyright (c) 2019, Leonid Titov, Mentions Highly Appreciated.

    var id_cnt = 1;
    var all_old_objects = {};
    var all_new_objects = {};
    var root_obj = this;

    if (root_obj === undefined) {
        console.log(`deep_copy() error: wrong call context`);
        return;
    }

    var new_obj = copy_obj(root_obj);

    for (var id in all_old_objects) {
        delete all_old_objects[id].__temp_id;
    }

    return new_obj;
    //

    function copy_obj(o) {
        var new_obj = {};
        if (o.__temp_id === undefined) {
            o.__temp_id = id_cnt;
            all_old_objects[id_cnt] = o;
            all_new_objects[id_cnt] = new_obj;
            id_cnt ++;

            for (var prop in o) {
                if (o[prop] instanceof Array) {
                    new_obj[prop] = copy_array(o[prop]);
                }
                else if (o[prop] instanceof Object) {
                    new_obj[prop] = copy_obj(o[prop]);
                }
                else if (prop === '__temp_id') {
                    continue;
                }
                else {
                    new_obj[prop] = o[prop];
                }
            }
        }
        else {
            new_obj = all_new_objects[o.__temp_id];
        }
        return new_obj;
    }
    function copy_array(a) {
        var new_array = [];
        if (a.__temp_id === undefined) {
            a.__temp_id = id_cnt;
            all_old_objects[id_cnt] = a;
            all_new_objects[id_cnt] = new_array;
            id_cnt ++;

            a.forEach((v,i) => {
                if (v instanceof Array) {
                    new_array[i] = copy_array(v);
                }
                else if (v instanceof Object) {
                    new_array[i] = copy_object(v);
                }
                else {
                    new_array[i] = v;
                }
            });
        }
        else {
            new_array = all_new_objects[a.__temp_id];
        }
        return new_array;
    }
}

চিয়ার্স @!


1

এখানে ডিপক্লোন ফাংশন যা সমস্ত আদিম, অ্যারে, অবজেক্ট, ফাংশন ডেটা ধরণের পরিচালনা করে

function deepClone(obj){
	if(Array.isArray(obj)){
		var arr = [];
		for (var i = 0; i < obj.length; i++) {
			arr[i] = deepClone(obj[i]);
		}
		return arr;
	}

	if(typeof(obj) == "object"){
		var cloned = {};
		for(let key in obj){
			cloned[key] = deepClone(obj[key])
		}
		return cloned;	
	}
	return obj;
}

console.log( deepClone(1) )

console.log( deepClone('abc') )

console.log( deepClone([1,2]) )

console.log( deepClone({a: 'abc', b: 'def'}) )

console.log( deepClone({
  a: 'a',
  num: 123,
  func: function(){'hello'},
  arr: [[1,2,3,[4,5]], 'def'],
  obj: {
    one: {
      two: {
        three: 3
      }
    }
  }
}) ) 


1

এখানে আমার গভীর অনুলিপি অ্যালগোরিদম।

const DeepClone = (obj) => {
     if(obj===null||typeof(obj)!=='object')return null;
    let newObj = { ...obj };

    for (let prop in obj) {
      if (
        typeof obj[prop] === "object" ||
        typeof obj[prop] === "function"
      ) {
        newObj[prop] = DeepClone(obj[prop]);
      }
    }

    return newObj;
  };

টাইপফ (নাল) হিসাবে 'আপত্তি [প্রপ]! == নাল'ও' অবজেক্ট 'ফিরিয়ে দেয় কিনা তাও আপনার পরীক্ষা করতে হবে
প্রমোদ মালি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.