নোড.জেএস-তে একটি বস্তুর ক্লোনিং করা হচ্ছে


203

নোড.জেজে কোনও বস্তুর ক্লোন করার সর্বোত্তম উপায় কী

যেমন আমি পরিস্থিতি এড়াতে চাই যেখানে:

var obj1 = {x: 5, y:5};
var obj2 = obj1;
obj2.x = 6;
console.log(obj1.x); // logs 6

অবজেক্টটিতে অ্যাট্রিবিউট হিসাবে জটিল ধরণের থাকতে পারে, সুতরাং এর জন্য একটি সহজ (ভোজ এক্স অবজেক্ট 1) সমাধান করতে পারে না। আমার কি নিজেকে একটি পুনরাবৃত্ত ক্লোন লেখার দরকার আছে বা এমন কিছু তৈরি হয়েছে যা আমি দেখছি না?


23
1. npm install underscore2. var _ = require('underscore')3 _.clone(objToClone).;
সালমান ভন আব্বাস

4
উল্লেখ্য যে উপরে @ সালমানপিকে-র মন্তব্যে এটি একটি অগভীর ক্লোন। সুতরাং এটি স্লিফটির উদাহরণের জন্য কাজ করবে, তবে যদি নেস্টেড অ্যারে বা অবজেক্ট থাকে তবে সেগুলি রেফারেন্স হবে। : /
জেসি

1
আমি এই নিবন্ধটি খুব সহায়ক বলে মনে করেছি: heyjavascript.com/4-creative-ways-to-clone-objects
জর্ডান হাডসন

3
@ জর্ডান হাডসন - দ্বিতীয় উদাহরণে জেএসএনের খুব সুন্দর ব্যবহার। var newObj = JSON.parse (JSON.stringify (oldObj)); // এখন newObj একটি ক্লোন। কেবল সমস্যাটি হ'ল স্ট্রিংফাই পুনরাবৃত্তিক রেফারেন্সে কাজ করবে না তাই যত্নবান হওয়া দরকার।
কেফির ইরজ

উত্তর:


298

সম্ভাব্যতা ঘ

লো-ফ্রিলস গভীর অনুলিপি:

var obj2 = JSON.parse(JSON.stringify(obj1));

সম্ভাব্যতা 2 (অবমূল্যায়িত)

মনোযোগ দিন: এই সমাধানটি এখন নোড.জেএস এর ডকুমেন্টেশনে অবচয় হিসাবে চিহ্নিত হয়েছে :

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

এটি অবচয় করা হয়েছে এবং নতুন কোডে ব্যবহার করা উচিত নয়। জাভাস্ক্রিপ্ট অবজেক্ট.সেসাইন () এর মাধ্যমে খুব অনুরূপ বিল্ট-ইন কার্যকারিতা নিয়ে আসে।

আসল উত্তর :

অগভীর কপির জন্য নোডের অন্তর্নির্মিত util._extend()ফাংশনটি ব্যবহার করুন।

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

var obj1 = {x: 5, y:5};
var obj2 = extend({}, obj1);
obj2.x = 6;
console.log(obj1.x); // still logs 5

নোডের _extendক্রিয়াকলাপের উত্স কোডটি এখানে রয়েছে: https://github.com/joyent/node/blob/master/lib/util.js

exports._extend = function(origin, add) {
  // Don't do anything if add isn't an object
  if (!add || typeof add !== 'object') return origin;

  var keys = Object.keys(add);
  var i = keys.length;
  while (i--) {
    origin[keys[i]] = add[keys[i]];
  }
  return origin;
};

5
প্রশ্নটি বিশেষত পুনরাবৃত্ত ক্লোনটির জন্য ডেকে আনে। এটি একটি অগভীর ক্লোন।
বেনিয়ামিন আটকিন 21

28
নামটির _*অর্থ এটি কী কোনও ব্যক্তিগত পদ্ধতি এবং এর উপর নির্ভর করা উচিত নয়?
ফ্লফি

7
যে কোনও আকারের প্রতিটি জাভাস্ক্রিপ্ট প্রকল্পের প্রসারিত () এর এক বা একাধিক বাস্তবায়ন রয়েছে এবং নোডও এর ব্যতিক্রম নয়। নোড.জেএস কোর এই ফাংশনটির ব্যাপক ব্যবহার করে। আইজ্যাকসকে উদ্ধৃত করার জন্য, "শীঘ্রই এটি আর কোথাও যাচ্ছে না।"
জিম্বো

2
আমার জন্য পুরোপুরি কাজ। অবজেক্ট প্রোটোটাইপ ইমো নিয়ে
গোলমাল

12
এটি সঠিক উত্তর। নোড এর ডকুমেন্টেশন অনুযায়ী: nodejs.org/api/util.html#util_util_extend_obj পদ্ধতি অভ্যন্তরীণ Node.js মডিউলগুলি ব্যবহৃত বাহিরে হতে উদ্দেশ্যে না হয়। সম্প্রদায় এটি যেভাবেই খুঁজে পেয়েছিল এবং ব্যবহার করেছে। এটি অবচয় করা হয়েছে এবং নতুন কোডে ব্যবহার করা উচিত নয়। জাভাস্ক্রিপ্ট খুব অনুরূপ বিল্ট-ইন কার্যকারিতার মাধ্যমে আসেutil._extend() Object.assign().
জর্ডি

264

আমি অবাক হয়েছি বলে কিছু Object.assignবলা হয়নি।

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

যদি উপলভ্য হয় (যেমন বাবেল), আপনি অবজেক্ট স্প্রেড অপারেটরটি ব্যবহার করতে পারেন :

let cloned = { ... source };

1
তুমি আমার দিন বাঁচিয়েছ! ধন্যবাদ
wzr1337

2
এটি তৃতীয় পক্ষের লাইব্রেরি আমদানি করা বা অসম্পূর্ণ JSON ওয়ার্কআউন্ড ব্যবহার করার চেয়ে অনেক ভাল সমাধান। ধন্যবাদ!
নিল এস

75
এটি একটি অগভীর অনুলিপি
জর্দান ডেভিডসন

14
ডিপ ক্লোনটির জন্য সতর্কতা, গভীর ক্লোনটির জন্য এখনও অন্যান্য বিকল্প ব্যবহার করা দরকার। বিকাশকারী.মোজিলা.আর.ইন-
ইউএস

1
আমি অবজেক্ট স্প্রেড অপারেটরকে যা বলতে পারি তা কোনও ES6 জিনিস নয় পরিবর্তে একটি পর্যায় 3 প্রস্তাব। যার অর্থ আপনি এটি ব্যাবেল দিয়ে ব্যবহার করতে পারেন তবে আমি যা বুঝি তা ছাড়াই। github.com/tc39/…
macdja38

24
Object.defineProperty(Object.prototype, "extend", {
    enumerable: false,
    value: function(from) {
        var props = Object.getOwnPropertyNames(from);
        var dest = this;
        props.forEach(function(name) {
            if (name in dest) {
                var destination = Object.getOwnPropertyDescriptor(from, name);
                Object.defineProperty(dest, name, destination);
            }
        });
        return this;
    }
});

এটি আপনি ব্যবহার করতে পারেন এমন একটি বর্ধিত পদ্ধতি নির্ধারণ করবে। কোড এই নিবন্ধ থেকে আসে


এটি কীভাবে কাজ করার কথা তা আমি দেখছি না। এটি আসল অবজেক্টটি সংশোধন করে! কোনও অবজেক্টের ক্লোন পেতে আমার এই ফাংশনটি কীভাবে ব্যবহার করার কথা? আপনি কি এখানে কিছু ব্যবহারের কোড যুক্ত করতে পারেন? আপনার পোস্ট এবং ব্লগ পোস্ট পড়ার পরে, আমি এখনও বুঝতে পারি না যে এটি কীভাবে কোনও অবজেক্টের ক্লোনিংয়ের জন্য ব্যবহার করার উদ্দেশ্যে।
ব্র্যাড

3
এটি কি সত্যিই কাজ করে? "যদি (নিয়মে নাম)" - সম্পত্তিটি ইতিমধ্যে এটি নিয়মে উপস্থিত থাকলে কেবল পরিবর্তন করবে। এটি অবহেলা করা উচিত।
স্মরণীয়

8
অবজেক্ট.প্রোটোটাইপটি সংশোধন করে ভারবোটেন বলে মনে করা হচ্ছে না? এছাড়াও সেই নিবন্ধটির লিঙ্কটি নষ্ট হয়ে গেছে।
ড্যানিয়েল শেফার

কেবল নিবন্ধের লিঙ্কটি চেষ্টা করে দেখলাম এটি আমার পক্ষে কাজ করে। আপনি এটি চেষ্টা করার সময় এটি কোনও নেটওয়ার্ক ব্লিপ ছিল।
মাইকেল ডিলন

বেশ কয়েকটি মন্তব্যের ভিত্তিতে, আমি উত্তরটি আপডেট করেছি একটি বৈকল্পিক অন্তর্ভুক্ত করার জন্য যা বস্তুর প্রোটোটাইপে যুক্ত হয় না।
শামাসিস ভট্টাচার্য

20
var obj2 = JSON.parse(JSON.stringify(obj1));

2
এটি ইতিমধ্যে বিদ্যমান জবাবটিতে এটি পুনরাবৃত্তি করার কোনও পরামর্শ নেই।
শেডো উইজার্ড আপনার পক্ষে কান

@ শ্যাডো উইজার্ড এগুলি বিভিন্ন পদ্ধতি। এই একটিকে কেবল জসনে রূপান্তরিত করে এবং বস্তুতে ফিরে আসে, Object.keys()
লিঙ্কিত

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

13

আপনি JQuery থেকে প্রসারিত ফাংশনটি ব্যবহার করতে পারেন:

var newClone= jQuery.extend({}, oldObject);  
var deepClone = jQuery.extend(true, {}, oldObject); 

একটি নোড.জেএস প্লাগইনও রয়েছে:

https://github.com/shimondoodkin/nodejs-clone-extend

JQuery বা প্লাগইন ছাড়াই এটি করতে এখানে এটি পড়ুন:

http://my.opera.com/GreyWyvern/blog/show.dml/1725165


নোড.জেএস প্লাগইন নিখুঁত। ধন্যবাদ!
জাস্টিন

দুর্দান্ত উত্তর। আমি সামান্য দরকারী মডিউল পছন্দ।
শেভ


8

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

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

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


7

এই কোডটি কাজের কারণ হিসাবেও অবজেক্ট.ক্রিয়েট () পদ্ধতিটি নির্দিষ্ট প্রোটোটাইপ অবজেক্ট এবং বৈশিষ্ট্য সহ একটি নতুন অবজেক্ট তৈরি করে।

var obj1 = {x:5, y:5};

var obj2 = Object.create(obj1);

obj2.x; //5
obj2.x = 6;
obj2.x; //6

obj1.x; //5

4
এটি একটি অগভীর অনুলিপি
ব্রাউন ব্রাউন মার্ড

6

নোডজেএস-তে কোনও অবজেক্ট ক্লোন করার সহজ এবং দ্রুততম উপায় হ'ল অবজেক্ট.কিজ (অবজেক্ট) পদ্ধতিটি ব্যবহার করা is

var a = {"a": "a11", "b": "avc"};
var b;

for(var keys = Object.keys(a), l = keys.length; l; --l)
{
   b[ keys[l-1] ] = a[ keys[l-1] ];
}
b.a = 0;

console.log("a: " + JSON.stringify(a)); // LOG: a: {"a":"a11","b":"avc"} 
console.log("b: " + JSON.stringify(b)); // LOG: b: {"a":0,"b":"avc"}

অবজেক্ট.কিগুলি পদ্ধতিতে জাভাস্ক্রিপ্ট ১.৮.৫ প্রয়োজন; নোডজেএস v0.4.11 এই পদ্ধতিটি সমর্থন করে

তবে অবশ্যই নেস্টেড বস্তুর জন্য পুনরাবৃত্ত ফানক প্রয়োগ করা দরকার


অন্যান্য সমাধান হ'ল দেশীয় জেএসএন ব্যবহার করুন (জাভাস্ক্রিপ্ট ১.7 এ প্রয়োগ করা হয়েছে) তবে এটি আগেরটির তুলনায় অনেক ধীর (~ 10 গুণ ধীর)

var a = {"a": i, "b": i*i};
var b = JSON.parse(JSON.stringify(a));
b.a = 0;

5

গিথুব-এ একটি প্রকল্পও রয়েছে যার লক্ষ্য এর আরও একটি সরাসরি বন্দর হতে হবে jQuery.extend():

https://github.com/dreamerslab/node.extend

JQuery ডক্স থেকে পরিবর্তিত একটি উদাহরণ :

var extend = require('node.extend');

var object1 = {
    apple: 0,
    banana: {
        weight: 52,
        price: 100
    },
    cherry: 97
};

var object2 = {
    banana: {
        price: 200
    },
    durian: 100
};

var merged = extend(object1, object2);


3

সত্যিকারের ক্লোন বিকল্পের সন্ধানে, আমি এখানে উপহাসের লিঙ্কটি পেরেছি:

http://my.opera.com/GreyWyvern/blog/show.dml/1725165

আমি সেই পৃষ্ঠাটিতে সমাধানটি সংশোধন করেছি যাতে Objectপ্রোটোটাইপের সাথে সংযুক্ত ফাংশনটি গণনীয় না হয়। এখানে আমার ফলাফল:

Object.defineProperty(Object.prototype, 'clone', {
    enumerable: false,
    value: function() {
        var newObj = (this instanceof Array) ? [] : {};
        for (i in this) {
        if (i == 'clone') continue;
            if (this[i] && typeof this[i] == "object") {
                newObj[i] = this[i].clone();
            } else newObj[i] = this[i]
        } return newObj;
    }
});

আশা করি এটি অন্য কাউকেও সহায়তা করে। মনে রাখবেন যে কিছু ক্যাভ্যাট রয়েছে ... বিশেষত "ক্লোন" নামের বৈশিষ্ট্যযুক্ত। এটি আমার পক্ষে ভাল কাজ করে। এটি লেখার জন্য আমি কোনও কৃতিত্ব গ্রহণ করি না। আবার, আমি কেবল পরিবর্তন করেছি যে এটি কীভাবে সংজ্ঞায়িত করা হচ্ছে।


এটা ভুল. তারিখের প্রকারটি অবজেক্ট তাই এই কোডটি খালি বস্তু দ্বারা তারিখগুলি প্রতিস্থাপন করবে ... এটি ব্যবহার করবেন না।
jtblin



0

আপনি যদি কফি-স্ক্রিপ্ট ব্যবহার করেন তবে এটি এতটা সহজ:

newObject = {}
newObject[key] = value  for own key,value of oldObject

যদিও এটি কোনও গভীর ক্লোন নয়।


0

উত্তরের কোনওটিই আমাকে সন্তুষ্ট করেনি, বেশ কয়েকটি কাজ করে না বা কেবল অগভীর ক্লোন হয়, @ ক্লিন্ট-হ্যারিসের উত্তর এবং জেএসএন.পার্স / স্ট্রিংফাই ব্যবহার করা ভাল তবে বেশ ধীর। আমি একটি মডিউল পেয়েছি যা গভীর ক্লোনিং দ্রুত করে: https://github.com/AlexeyKupershtokh/node-v8-clone


0

নোড.জেএস-তে কোনও বস্তুর আসল ক্লোন (গভীর অনুলিপি) করার কোনও অন্তর্নির্মিত উপায় নেই। কিছু জটিল প্রান্তের কেস রয়েছে তাই আপনার অবশ্যই এটির জন্য একটি লাইব্রেরি ব্যবহার করা উচিত। আমি আমার সরল লাইব্রেরির জন্য এই জাতীয় একটি অনুষ্ঠান লিখেছি । আপনি ব্যবহার করতে পারেন deepCopyলাইব্রেরি থেকে অন্য কিছু ব্যবহার (যা বেশ ছোট হয়) আপনি এটা প্রয়োজন হবে না ছাড়া ফাংশন। এই ফাংশনটি অ্যারে, তারিখগুলি এবং নিয়মিত এক্সপ্রেশন সহ একাধিক ডেটা ধরণের ক্লোনিং সমর্থন করে, এটি পুনরাবৃত্ত তথ্যসূত্রগুলি সমর্থন করে এবং এটি এমন বস্তুর সাথেও কাজ করে যার নির্মাণকারীর কার্যাদি প্রয়োজনীয় পরামিতি রয়েছে have

কোডটি এখানে:

//If Object.create isn't already defined, we just do the simple shim, without the second argument,
//since that's all we need here
var object_create = Object.create;
if (typeof object_create !== 'function') {
    object_create = function(o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}

/**
 * Deep copy an object (make copies of all its object properties, sub-properties, etc.)
 * An improved version of http://keithdevens.com/weblog/archive/2007/Jun/07/javascript.clone
 * that doesn't break if the constructor has required parameters
 * 
 * It also borrows some code from http://stackoverflow.com/a/11621004/560114
 */ 
function deepCopy = function deepCopy(src, /* INTERNAL */ _visited) {
    if(src == null || typeof(src) !== 'object'){
        return src;
    }

    // Initialize the visited objects array if needed
    // This is used to detect cyclic references
    if (_visited == undefined){
        _visited = [];
    }
    // Ensure src has not already been visited
    else {
        var i, len = _visited.length;
        for (i = 0; i < len; i++) {
            // If src was already visited, don't try to copy it, just return the reference
            if (src === _visited[i]) {
                return src;
            }
        }
    }

    // Add this object to the visited array
    _visited.push(src);

    //Honor native/custom clone methods
    if(typeof src.clone == 'function'){
        return src.clone(true);
    }

    //Special cases:
    //Array
    if (Object.prototype.toString.call(src) == '[object Array]') {
        //[].slice(0) would soft clone
        ret = src.slice();
        var i = ret.length;
        while (i--){
            ret[i] = deepCopy(ret[i], _visited);
        }
        return ret;
    }
    //Date
    if (src instanceof Date) {
        return new Date(src.getTime());
    }
    //RegExp
    if (src instanceof RegExp) {
        return new RegExp(src);
    }
    //DOM Element
    if (src.nodeType && typeof src.cloneNode == 'function') {
        return src.cloneNode(true);
    }

    //If we've reached here, we have a regular object, array, or function

    //make sure the returned object has the same prototype as the original
    var proto = (Object.getPrototypeOf ? Object.getPrototypeOf(src): src.__proto__);
    if (!proto) {
        proto = src.constructor.prototype; //this line would probably only be reached by very old browsers 
    }
    var ret = object_create(proto);

    for(var key in src){
        //Note: this does NOT preserve ES5 property attributes like 'writable', 'enumerable', etc.
        //For an example of how this could be modified to do so, see the singleMixin() function
        ret[key] = deepCopy(src[key], _visited);
    }
    return ret;
};

0
npm install node-v8-clone

দ্রুততম ক্লোনার, এটি নোড.জেএস থেকে নেটিভ ক্লোন পদ্ধতি খোলে

var clone = require('node-v8-clone').clone;
var newObj = clone(obj, true); //true - deep recursive clone

0

আরেকটি সমাধান হ'ল নতুন ভেরিয়েবলটি সরাসরি ব্যবহার করে এটি ব্যবহার করে: obj1= {...obj2}


এটি একটি অগভীর অনুলিপি
রুমি দুলেগে


-2

আপনি বস্তুর প্রোটোটাইপ করতে পারেন এবং তারপরে প্রতিবার আপনি যখন অবজেক্ট ব্যবহার করতে এবং পরিবর্তন করতে চান তখন অবজেক্ট ইনস্ট্যান্সটি কল করতে পারেন:

function object () {
  this.x = 5;
  this.y = 5;
}
var obj1 = new object();
var obj2 = new object();
obj2.x = 6;
console.log(obj1.x); //logs 5

আপনি অবজেক্ট কনস্ট্রাক্টরের কাছে আর্গুমেন্টও পাস করতে পারেন

function object (x, y) {
   this.x = x;
   this.y = y;
}
var obj1 = new object(5, 5);
var obj2 = new object(6, 6);
console.log(obj1.x); //logs 5
console.log(obj2.x); //logs 6

আশা করি এটি সহায়ক।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.