নোডেজ: কীভাবে কোনও বস্তুর ক্লোন করা যায়


91

যদি আমি কোনও অ্যারে ক্লোন করি তবে আমি ব্যবহার করি cloneArr = arr.slice()

আমি জানতে চাই কিভাবে নোডজেজে কোনও বস্তুর ক্লোন করতে হয়।

উত্তর:


178

ইউটিলিটি এবং ক্লাসগুলির জন্য যেখানে প্রতিটি ড্রপ সম্পাদন করার প্রয়োজন নেই, আমি প্রায়শই প্রতারণা করি এবং একটি গভীর অনুলিপি সম্পাদনের জন্য কেবল JSON ব্যবহার করি:

function clone(a) {
   return JSON.parse(JSON.stringify(a));
}

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


4
@ ডিজেচলিন অবশ্যই তা করবেন এটি ব্যবহার করে দেখুন: jsfiddle.net/katowulf/E5jC3 (নোড ০.১০.১১ এর সাথে পরীক্ষা করা) এটি ফাংশন বা প্রোটোটাইপিকাল ডেটা পুনর্গঠন করতে সক্ষম হতে পারে না, তবে এটি কেবল সূক্ষ্মের আশেপাশের মানগুলি পায়।
কাটো

13
এটি তারিখগুলিকে স্ট্রিংয়ে রূপান্তর করবে
ব্যাকাস

4
@ ব্যাকাস পাশাপাশি বস্তু এবং ক্রিয়াকলাপ।
কাটো

4
@ কাতো, বিজ্ঞপ্তি উল্লেখগুলি কেন বোঝায় যে গভীর অনুলিপিগুলি তৈরি করার দরকার নেই? এগুলি দুটি সম্পর্কিত নয়। নোডজেএস-এর পক্ষে একটি ভাল ক্লোন পদ্ধতি লিখতে সম্ভবত এটি সম্ভব যা বিজ্ঞপ্তি রেফারেন্সগুলিকে সমর্থন করে এবং ক্লোন করতে JSON ব্যবহার করে পিছিয়ে পড়ে না। github.com/pvorb/node-clone
স্যামুয়েল নেফ

4
মন্তব্য এবং বর্ণনায় ইতিমধ্যে উল্লিখিত। আপনি কোনও জেনেরিক ক্লোন পদ্ধতিতে কোনও ফাংশন, অবজেক্ট প্রোটোটাইপ বা অন্যান্য জিনিসগুলির ক্লোন করতে পারবেন না। এর জন্য আপনার একাধিক লাইন কোডের প্রয়োজন হবে, এবং সম্ভবত যে কোনও উপায়ে জাঙ্কটি ক্লোন করা উচিত নয় - আপনার ক্লাসে এমন একটি ক্লোন পদ্ধতি স্থাপন করুন যা ইন্টার্নালগুলি পরিচালনা করতে এবং কীভাবে জানেnewObj = obj.clone(args...);
কাতো

35

ওজেক্ট.স্যাসাইন উপরের কোনও উত্তরে উল্লেখ করা হয়নি।

let cloned = Object.assign({}, source);

আপনি ES6 এ থাকলে আপনি স্প্রেড অপারেটরটি ব্যবহার করতে পারেন:

let cloned = { ... source };

তথ্যসূত্র: https://developer.mozilla.org/en-US/docs/Web/ জাভা স্ক্রিপ্ট / রেফারেন্স / গ্লোবাল_অবজেক্টস / অবজেক্ট / পাস


29
মনে রাখবেন যে এই দুটিই অগভীর ক্লোন এবং বস্তুর স্প্রেড অপারেটরের জন্য নোড.জেএস 8+ প্রয়োজন।
jlh

4
@ জেএলএইচ হিসাবে উল্লেখ করা হয়েছে যে এটি নেস্টেড বস্তুর জন্য কাজ করে না। আপনি এই পদ্ধতির গভীর ক্লোন ইস্যুতে এখানে আরও পড়তে পারেন: বিকাশকারী.মোজিলা.আর.ইন-
ইউএস

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

4
এটি ক্লোন করে না, এটি কেবল আসল অবজেক্টের উল্লেখ করে, মানে আপনি যদি কিছু পরিবর্তন করেন তবে এটি মাস্টারের কাছে যাবে
আইডান ওয়েলচ

পছন্দ করুন let a = {x:1}; let b = Object.assign({}, a); a.x = 2; a.y = 1; console.log(a, b);
মিগুয়েল পাইতো

20

"নিজের নিজস্ব রোল" না করতে চাইলে কিছু নোড মডিউল রয়েছে। এটি দেখতে দুর্দান্ত দেখাচ্ছে: https://www.npmjs.com/package/clone

দেখে মনে হচ্ছে এটি বিজ্ঞপ্তি সংক্রান্ত রেফারেন্স সহ সমস্ত ধরণের জিনিস পরিচালনা করে। থেকে GitHub পৃষ্ঠা:

ক্লোন মাস্টার ক্লোনিং অবজেক্টস, অ্যারে, তারিখ অবজেক্টস এবং রেজেক্সেক্স অবজেক্টস। সবকিছু পুনরাবৃত্তভাবে ক্লোন করা হয়, যাতে আপনি বস্তুগুলিতে অ্যারেতে তারিখগুলি ক্লোন করতে পারেন। [...] বিজ্ঞপ্তি রেফারেন্স? হ্যাঁ!


10

জেনেরিক কিন্তু দরকারী ক্লোন অপারেশন করা শক্ত কারণ কারণ পুনরাবৃত্তভাবে কীভাবে ক্লোন করা উচিত এবং কী কী অনুলিপি করা উচিত তা নির্ভর করে নির্দিষ্ট বিষয়টিকে কীভাবে কাজ করা উচিত তার উপর নির্ভর করে।

কিছু কার্যকর হতে পারে

function clone(x)
{
    if (x === null || x === undefined)
        return x;
    if (typeof x.clone === "function")
        return x.clone();
    if (x.constructor == Array)
    {
        var r = [];
        for (var i=0,n=x.length; i<n; i++)
            r.push(clone(x[i]));
        return r;
    }
    return x;
}

এই কোডটিতে যুক্তিটি হ'ল

  • ক্ষেত্রে nullবা undefinedকেবল একইটি ফিরে আসার ক্ষেত্রে (বিশেষ ক্ষেত্রে প্রয়োজন কারণ এটি কোনও cloneপদ্ধতি উপস্থিত রয়েছে কিনা তা দেখার চেষ্টা করার জন্য একটি ত্রুটি )
  • বস্তুর কি আছে? clone পদ্ধতি আছে? তারপরে এটি ব্যবহার করুন
  • বস্তু একটি অ্যারে হয়? তারপরে একটি পুনরাবৃত্ত ক্লোনিং অপারেশন করুন
  • অন্যথায় কেবল একই মানটি ফিরিয়ে দিন

এই ক্লোন ফাংশনটি সহজেই কাস্টম ক্লোন পদ্ধতিগুলি প্রয়োগ করার অনুমতি দেয় ... উদাহরণস্বরূপ

function Point(x, y)
{
    this.x = x;
    this.y = y;

    ...
}

Point.prototype.clone = function()
{
    return new Point(this.x, this.y);
};



function Polygon(points, style)
{
    this.points = points;
    this.style = style;

    ...
}

Polygon.prototype.clone = function()
{
    return new Polygon(clone(this.points),
                       this.style);
};

যখন অবজেক্টে আপনি জানেন যে একটি নির্দিষ্ট অ্যারের জন্য সঠিক ক্লোনিং অপারেশন কেবল একটি অগভীর অনুলিপি হয় তখন আপনি values.slice()পরিবর্তে কল করতে পারেনclone(values)

উদাহরণস্বরূপ উপরের কোডে আমি স্পষ্টভাবে প্রয়োজনীয়ভাবে বলছি যে বহুভুজ অবজেক্টের ক্লোনিং পয়েন্টগুলি ক্লোন করবে তবে একই স্টাইলের অবজেক্টটি ভাগ করে নেবে। আমি যদি এর পরিবর্তে স্টাইলের অবজেক্টটিকে ক্লোন করতে চাই তবে আমি কেবল পাস করতে পারি clone(this.style)


4
+1 উল্লেখ করার জন্য যে বস্তুর নিজস্ব .cloneপদ্ধতি প্রয়োগ করা দরকার implement ক্লোনিং অবজেক্টগুলির সাথে ডিল করার সেরা উপায়।
রায়নোস

4
if (x.clone)হওয়া উচিতif (typeof x.clone === 'function')
ইয়ানিক রোচন

@ ইয়ানিকরোচন: ধন্যবাদ, স্থির দুঃখিত, কোনওরকম আমি এর আগে এই মন্তব্যটি লক্ষ্য করিনি ...
6502

9

ক্লোনিং অবজেক্টের জন্য কোনও দেশীয় পদ্ধতি নেই। অধ্যয়নগুলি _.cloneযা অগভীর ক্লোন।

_.clone = function(obj) {
  return _.isArray(obj) ? obj.slice() : _.extend({}, obj);
};

এটি হয় এটি টুকরো টুকরো করে বা প্রসারিত করে।

এখানে _.extend

// extend the obj (first parameter)
_.extend = function(obj) {
  // for each other parameter
  each(slice.call(arguments, 1), function(source) {
    // loop through all properties of the other objects
    for (var prop in source) {
      // if the property is not undefined then add it to the object.
      if (source[prop] !== void 0) obj[prop] = source[prop];
    }
  });
  // return the object (first parameter)
  return obj;
};

সমস্ত আইটেমের মাধ্যমে কেবল পুনরাবৃত্তি প্রসারিত করুন এবং এতে থাকা আইটেমগুলির সাথে একটি নতুন অবজেক্ট তৈরি করুন।

আপনি চাইলে আপনার নিজের নিষ্পাপ প্রয়োগ বাস্তবায়ন করতে পারেন

function clone(o) {
  var ret = {};
  Object.keys(o).forEach(function (val) {
    ret[val] = o[val];
  });
  return ret;
}

গভীর ক্লোনিং এড়ানোর ভাল কারণ রয়েছে কারণ ক্লোজারগুলি ক্লোন করা যায় না।

আমি ব্যক্তিগতভাবে একটি প্রশ্ন জিজ্ঞাসা করেছি deep cloning objects beforeএবং আমি যে সিদ্ধান্তে এসেছি তা হ'ল আপনি কেবল এটি করেন না।

আমার সুপারিশটি ব্যবহার underscoreএবং _.cloneঅগভীর ক্লোনগুলির জন্য এটির পদ্ধতি


9

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

var newObject = Object.keys(original).reduce(function (obj, item) {
    obj[item] = original[item];
    return obj;
},{});

কয়েকটি বিকল্পের জন্য এখানে একটি জাসস্পিফ রয়েছে: http://jsperf.com/shallow-copying


সরল, মার্জিত, উজ্জ্বল। আমি আপনার অন্যান্য এসও অবদানের অপেক্ষায় রয়েছি ^ _ ^
আপনাকে ধন্যবাদ 21

7

পুরানো প্রশ্ন, তবে এখনও অবধি যা পরামর্শ দেওয়া হয়েছে তার থেকেও আরও মার্জিত উত্তর রয়েছে; অন্তর্নির্মিত ব্যবহারগুলি ব্যবহার করুন।

var extend = require("util")._extend;

var varToCopy = { test: 12345, nested: { val: 6789 } };

var copiedObject = extend({}, varToCopy);

console.log(copiedObject);

// outputs:
// { test: 12345, nested: { val: 6789 } }

খালি অবজেক্ট with} সহ প্রথম প্যারামিটারের ব্যবহারটি নোট করুন - এটি প্রসারিত করে যে অনুলিপি করা অবজেক্ট (গুলি) একটি নতুন অবজেক্টে অনুলিপি করা দরকার। আপনি যদি কোনও বিদ্যমান অবজেক্টটিকে প্রথম প্যারামিটার হিসাবে ব্যবহার করেন তবে দ্বিতীয় (এবং পরবর্তী সমস্ত) পরামিতিগুলি প্রথম প্যারামিটার ভেরিয়েবলের উপর গভীর-সংশ্লেষ-অনুলিপি করা হবে।

উপরের উদাহরণ ভেরিয়েবলগুলি ব্যবহার করে আপনি এটি করতে পারেন:

var anotherMergeVar = { foo: "bar" };

extend(copiedObject, { anotherParam: 'value' }, anotherMergeVar);

console.log(copiedObject);

// outputs:
// { test: 12345, nested: { val: 6789 }, anotherParam: 'value', foo: 'bar' }

খুব সুবিধাজনক ইউটিলিটি, বিশেষত যেখানে আমি AngularJS এবং jQuery এ প্রসারিত করতে ব্যবহার করছি used

আশাকরি এটি কাউকে সাহায্য করবে; অবজেক্ট রেফারেন্স ওভাররাইটগুলি একটি দুর্ভাগ্য, এবং এটি প্রতিবারই এটি সমাধান করে!


4
_Extend ব্যবহার করা এখন অবমূল্যায়িত। পরিবর্তে অবজেক্ট.সেসাইন () ব্যবহার করুন: বিকাশকারী.মোজিলা.আর.ইন.ইউএস
ডকস / ওয়েব

7

আপনি পাশাপাশি লোডাশ ব্যবহার করতে পারেন । এটিতে একটি ক্লোন এবং ক্লোনডিপ পদ্ধতি রয়েছে।

var _= require('lodash');

var objects = [{ 'a': 1 }, { 'b': 2 }];

var shallow = _.clone(objects);
console.log(shallow[0] === objects[0]);
// => true

var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]);

1

আপনার ক্লোন করা অবজেক্টের সাথে আপনি কী করতে চান তার উপর নির্ভর করে আপনি জাভাস্ক্রিপ্টের প্রোটোটাইপাল উত্তরাধিকার প্রক্রিয়াটি ব্যবহার করতে পারেন এবং এর মাধ্যমে কিছুটা ক্লোন করা বস্তু অর্জন করতে পারেন:

var clonedObject = Object.create(originalObject);

কেবল মনে রাখবেন যে এটি সম্পূর্ণ ক্লোন নয় - আরও ভাল বা আরও খারাপের জন্য।

সে সম্পর্কে একটি ভাল বিষয় হ'ল আপনি আসলে অবজেক্টটির সদৃশ করেন নি তাই মেমরির পদক্ষেপ কম হবে।

এই পদ্ধতি সম্পর্কে মনে রাখার জন্য কিছু জটিল বিষয়গুলি হ'ল প্রোটোটাইপ চেইনে সংজ্ঞায়িত বৈশিষ্ট্যের পুনরাবৃত্তি কখনও কখনও কিছুটা আলাদা কাজ করে এবং মূল বস্তুর কোনও পরিবর্তন ক্লোনযুক্ত বস্তুকেও প্রভাবিত করবে যদি না সেই সম্পত্তি নিজেই সেট করা না থাকে unless ।


4
এটি এতটাই হাস্যকর বিপজ্জনক এবং একেবারে ক্লোন থেকে ভিন্ন। var a = {foo: "bar"}, b = Object.create(a); a.foo = "broken"; console.log(b.foo); // "broken";
আপনাকে ধন্যবাদ

@ নোমিক: b.foo = "working"; console.log(a.foo); // still "broken";অবশ্যই একটি সচেতন হতে হবে যে মূল বস্তুর পরিবর্তনগুলি "ক্লোন" এ প্রতিফলিত হবে এবং "ক্লোন" এর পরিবর্তনগুলি মূল বস্তুতে প্রতিফলিত হবে না - তবে আমি এটিকে বিপজ্জনক বলব না - এটি সমস্তই আপনার
ক্লোনটির

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

@ বিমরনিন, আপনি যদি ওলি কে-এর কৌশল ব্যবহার করেন তবে মূল বস্তুটি সংশোধন করা নতুন বস্তুর পরিবর্তনের কারণ হতে পারে না
আপনাকে ধন্যবাদ

4
@VoxPelli একটি "ক্লোন" পুরো উদ্দেশ্য মূল বস্তু থেকে বিছিন্ন পরিবর্তন করা হয়, অত: পর এই পদ্ধতি হল বেশী বিপজ্জনক।
ডগ

1

আমি একটি সম্পূর্ণ গভীর অনুলিপি প্রয়োগ করেছি। আমি বিশ্বাস করি যে এটি জেনেরিক ক্লোন পদ্ধতির জন্য সেরা চয়ন, তবে এটি চক্রীয় রেফারেন্সগুলি পরিচালনা করে না।

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

parent = {'prop_chain':3}
obj = Object.create(parent)
obj.a=0; obj.b=1; obj.c=2;

obj2 = copy(obj)

console.log(obj, obj.prop_chain)
// '{'a':0, 'b':1, 'c':2} 3
console.log(obj2, obj2.prop_chain)
// '{'a':0, 'b':1, 'c':2} 3

parent.prop_chain=4
obj2.a = 15

console.log(obj, obj.prop_chain)
// '{'a':0, 'b':1, 'c':2} 4
console.log(obj2, obj2.prop_chain)
// '{'a':15, 'b':1, 'c':2} 4

কোড নিজেই:

এই কোডটি তাদের প্রোটোটাইপগুলির সাথে অবজেক্টগুলি অনুলিপি করে, এটি ফাংশনগুলিও অনুলিপি করে (কারও পক্ষে কার্যকর হতে পারে)।

function copy(obj) {
  // (F.prototype will hold the object prototype chain)
  function F() {}
  var newObj;

  if(typeof obj.clone === 'function')
    return obj.clone()

  // To copy something that is not an object, just return it:
  if(typeof obj !== 'object' && typeof obj !== 'function' || obj == null)
    return obj;

  if(typeof obj === 'object') {    
    // Copy the prototype:
    newObj = {}
    var proto = Object.getPrototypeOf(obj)
    Object.setPrototypeOf(newObj, proto)
  } else {
    // If the object is a function the function evaluate it:
    var aux
    newObj = eval('aux='+obj.toString())
    // And copy the prototype:
    newObj.prototype = obj.prototype
  }

  // Copy the object normal properties with a deep copy:
  for(var i in obj) {
    if(obj.hasOwnProperty(i)) {
      if(typeof obj[i] !== 'object')
        newObj[i] = obj[i]
      else
        newObj[i] = copy(obj[i])
    }
  }

  return newObj;
}

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

আমি আসা করি এটা সাহায্য করবে


1

অ্যারে জন্য, একটি ব্যবহার করতে পারেন

var arr = [1,2,3]; 
var arr_2 = arr ; 

print ( arr_2 ); 

arr = arr.slice (0);

print ( arr ); 

arr[1]=9999; 

print ( arr_2 ); 

1

জাভাস্ক্রিপ্টে অবজেক্টস এবং অ্যারেগুলি রেফারেন্স অনুসারে কল ব্যবহার করে, আপনি যদি অনুলিপি করা মানটি আপডেট করেন তবে এটি আসল বস্তুর প্রতিফলন ঘটতে পারে। এটি প্রতিরোধের জন্য আপনি লোড্যাশ লাইব্রেরি ক্লোনডিপ পদ্ধতি রান কমান্ডটি ব্যবহার করে রেফারেন্সটি পাস করতে বাধা দিতে গভীরভাবে ক্লোন করতে পারেন

এনএমপি লোডাশ ইনস্টল করুন

const ld = require('lodash')
const objectToCopy = {name: "john", age: 24}
const clonedObject = ld.cloneDeep(objectToCopy)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.