एक चर के मूल्य को दूसरे में कॉपी करें


100

मेरे पास एक वैरिएबल है जिसके मूल्य के रूप में JSON ऑब्जेक्ट है। मैं सीधे इस चर को कुछ अन्य चर को सौंपता हूं ताकि वे समान मूल्य साझा करें। यह इस तरह काम करता है:

var a = $('#some_hidden_var').val(),
    b = a;

यह काम करता है और दोनों का मूल्य समान है। मैं अपने ऐप mousemoveको अपडेट करने के लिए एक इवेंट हैंडलर का उपयोग करता bहूं। एक बटन पर क्लिक करने पर, मैं bमूल मूल्य पर वापस लौटना चाहता हूं , जिसका अर्थ है कि संग्रहीत मूल्य a

$('#revert').on('click', function(e){
    b = a;
});

इसके बाद अगर मैं उसी mousemoveइवेंट हैंडलर का उपयोग करता हूं , तो यह दोनों को अपडेट करता है aऔर b, जब पहले यह केवल bअपेक्षा के अनुसार अपडेट हो रहा था ।

मैं इस मुद्दे पर फंस गया हूँ! यहाँ क्या गलत है?


कृपया अपने मूसमोव हैंडलर को दिखाएं। इसके अलावा, यह देखते हुए कि यह JSON (एक स्ट्रिंग) है, एक वस्तु नहीं है, यह aनिर्धारित किया गया था .val()- क्या यह सही है? क्या आप JSON.parse(a)वास्तविक वस्तु प्राप्त करने के लिए किसी बिंदु पर उपयोग करते हैं ?
nnnnnn

हां यह एक स्ट्रिंग है लेकिन मैं $.parseJSONइसे एक ऑब्जेक्ट में बदलने के लिए उपयोग करता हूं । संरचना: { 'key': {...}, 'key': {...}, ...}। क्षमा करें, यहां कोई भी कोड पोस्ट नहीं किया जा सकता है, मेरे कार्यस्थल में अनुमति नहीं है!
रुटविक गांगुर्ड

1
इतना है aएक वस्तु है?
आर्मंड

1
एक स्कूपिंग मुद्दे की तरह दिखता है .. aएक वैश्विक चर है?
मस्तूरी

2
आपके द्वारा दिखाए गए कोड में केवल तार हैं। यदि आप वस्तुओं की बात कर रहे हैं तो कई चर एक ही वस्तु को संदर्भित कर सकते हैं और ताकि किसी भी चर के माध्यम से वस्तु को उत्परिवर्तित किया जा सके। इसलिए अधिक कोड देखे बिना जो चर को हेरफेर करता है (इसमें कहां $.parseJSON()आता है?) यह कहना मुश्किल है कि समस्या क्या है। अपने कार्यस्थल के नियमों के बारे में, आपको अपना वास्तविक वास्तविक कोड पूरा करने की ज़रूरत नहीं है, बस एक छोटा और अधिक सामान्य उदाहरण पेश करें जो समस्या को प्रदर्शित करता है (और, आदर्श रूप से, jsfiddle.net पर लाइव डेमो के लिए एक लिंक शामिल करें ) ।
nnnnnn

जवाबों:


198

यह समझना महत्वपूर्ण है कि =जावास्क्रिप्ट में ऑपरेटर क्या करता है और क्या नहीं करता है।

=ऑपरेटर एक नहीं है प्रतिलिपि डेटा की।

=ऑपरेटर एक नया बनाता है संदर्भ के लिए एक ही डेटा।

अपना मूल कोड चलाने के बाद:

var a = $('#some_hidden_var').val(),
    b = a;

aऔर bअब एक ही वस्तु के दो अलग-अलग नाम हैं ।

इस ऑब्जेक्ट की सामग्री में आपके द्वारा किए गए किसी भी परिवर्तन को पहचान के रूप में देखा जाएगा चाहे आप इसे aचर या चर के माध्यम से देखें b। वे एक ही वस्तु हैं।

इसलिए, जब आप बाद में इस कोड के साथ bमूल aऑब्जेक्ट को "वापस" करने का प्रयास करते हैं :

b = a;

कोड वास्तव में कुछ भी नहीं करता है , क्योंकि aऔर bएक ही बात है। कोड वैसा ही है जैसा आपने लिखा है:

b = b;

जो स्पष्ट रूप से कुछ नहीं करेगा।

आपका नया कोड क्यों काम करता है?

b = { key1: a.key1, key2: a.key2 };

यहां आप {...}ऑब्जेक्ट शाब्दिक के साथ एक बिल्कुल नया ऑब्जेक्ट बना रहे हैं । यह नई वस्तु आपकी पुरानी वस्तु के समान नहीं है। तो अब आप bइस नई वस्तु के संदर्भ के रूप में सेट कर रहे हैं , जो आपको चाहिए।

किसी भी मनमानी ऑब्जेक्ट को संभालने के लिए, आप ऑब्जेक्ट क्लोनिंग फ़ंक्शन का उपयोग कर सकते हैं जैसे कि आर्मंड के उत्तर में सूचीबद्ध है, या जब से आप jQuery का उपयोग कर रहे हैं, तो $.extend()फ़ंक्शन का उपयोग करें । यह फ़ंक्शन या तो उथली प्रति या किसी वस्तु की गहरी प्रतिलिपि बना देगा। (इस $().clone()विधि के साथ भ्रमित न करें जो DOM तत्वों को कॉपी करने के लिए है, वस्तुओं के लिए नहीं।)

उथली प्रति के लिए:

b = $.extend( {}, a );

या एक गहरी प्रति:

b = $.extend( true, {}, a );

उथली प्रतिलिपि और गहरी प्रतिलिपि के बीच क्या अंतर है? एक उथली प्रति आपके कोड के समान है जो ऑब्जेक्ट शाब्दिक के साथ एक नई वस्तु बनाता है। यह एक नया शीर्ष-स्तरीय ऑब्जेक्ट बनाता है जिसमें मूल ऑब्जेक्ट के समान गुणों का संदर्भ होता है।

यदि आपकी वस्तु में केवल आदिम प्रकार हैं जैसे संख्या और तार, एक गहरी प्रतिलिपि और उथली प्रतिलिपि बिल्कुल वही काम करेगी। लेकिन अगर आपकी वस्तु में अन्य वस्तुएं या सरणियाँ निहित हैं, तो एक उथली प्रतिलिपि उन निहित वस्तुओं की प्रतिलिपि नहीं बनाती है , यह केवल उनके संदर्भ बनाता है। तो आपको नेस्टेड ऑब्जेक्ट्स के साथ वही समस्या हो सकती है जो आपके टॉप-लेवल ऑब्जेक्ट के साथ थी। उदाहरण के लिए, यह वस्तु दी गई है:

var obj = {
    w: 123,
    x: {
        y: 456,
        z: 789
    }
};

यदि आप उस वस्तु की उथली प्रतिलिपि करते xहैं , तो आपकी नई वस्तु की संपत्ति xमूल से समान वस्तु है:

var copy = $.extend( {}, obj );
copy.w = 321;
copy.x.y = 654;

अब आपकी वस्तुएँ इस तरह दिखेंगी:

// copy looks as expected
var copy = {
    w: 321,
    x: {
        y: 654,
        z: 789
    }
};

// But changing copy.x.y also changed obj.x.y!
var obj = {
    w: 123,  // changing copy.w didn't affect obj.w
    x: {
        y: 654,  // changing copy.x.y also changed obj.x.y
        z: 789
    }
};

आप इसे एक गहरी नकल से बचा सकते हैं। गहरी प्रतिलिपि प्रत्येक नेस्टेड ऑब्जेक्ट और सरणी (और आर्मंड के कोड में दिनांक) को उन वस्तुओं की प्रतियों को बनाने के लिए उसी तरह से पुन: बनाता है जिस तरह से यह शीर्ष-स्तरीय ऑब्जेक्ट की प्रतिलिपि बनाता है। इसलिए बदलाव copy.x.yका कोई असर नहीं पड़ेगा obj.x.y

संक्षिप्त उत्तर: यदि संदेह है, तो आप शायद एक गहरी प्रतिलिपि चाहते हैं।


धन्यवाद, यह वही है जिसकी मुझे तलाश थी। इसके आसपास काम करने का कोई तरीका? मेरी वर्तमान स्थिति में, यह ठीक करना आसान था क्योंकि मेरे पास केवल 2 गुण थे। लेकिन बड़ी वस्तुएं हो सकती हैं।
रटविक गंगूरडे

1
आर्मंड के जवाब में एक ऑब्जेक्ट क्लोन फ़ंक्शन है जो चाल करेगा। या जब से आप jQuery का उपयोग कर रहे हैं, आप अंतर्निहित $.extend()फ़ंक्शन का उपयोग कर सकते हैं । ऊपर विवरण। :-)
माइकल गेरी

महान व्याख्या माइकल!
रुटविक गांगुर्ड

7
@MichaelGeary यह नाइटपैकिंग हो सकता है लेकिन नियम केवल वस्तुओं पर लागू नहीं होते हैं और न ही आदिम चर? यह जवाब में ध्यान देने योग्य हो सकता है
जोनाथन डॉस सैंटोस

जेएस समाधान इसका उत्तर आर्मंड के उत्तर में है जैसे माइकल गेरी ने कहा। =
अलेक्जेंडरग्रिफिन

57

मैंने JSON कार्यों का उपयोग करते हुए पाया, लेकिन परिपत्र संदर्भों के लिए हमारा ध्यान रखें

var newInstance = JSON.parse(JSON.stringify(firstInstance));

2
मुझे एहसास हुआ कि यह थोड़ा देर से है, लेकिन क्या इस पद्धति के साथ कोई समस्या है? यह पहली कोशिश में आश्चर्यजनक रूप से काम करने लगता है।
मैनकाइंड 1023 17

2
यह लगभग हर स्थिति में बहुत अच्छा है, हालाँकि यदि आप डेटा के साथ काम कर रहे हैं जो कि विशेष होने की क्षमता रखता है, तो यह आपके प्रोग्राम को क्रैश कर देगा। कुछ कोड को स्पष्ट करने के लिए: let a = {}; let b = {a:a}; a.b = b; JSON.stringify(a)एक
टाइप करें

यह समाधान महान काम करता है। हालांकि, प्रसंस्करण के दौरान यह कितना महंगा है? ऐसा लगता है कि यह दोहरी उपेक्षा से काम करता है।
हाबिल कैलेजो

29

प्रश्न पहले से ही काफी लंबे समय से हल है, लेकिन भविष्य के संदर्भ के लिए एक संभव समाधान है

b = a.slice(0);

सावधान रहें, यह सही ढंग से केवल तभी काम करता है जब संख्याओं और तारों का गैर-नेस्टेड सरणी हो


23

newVariable = originalVariable.valueOf();

उन वस्तुओं के लिए जिनका आप उपयोग कर सकते हैं, b = Object.assign({},a);


3
उन वस्तुओं के लिए जिनका आप उपयोग कर सकते हैं, b = Object.assign ({}, a);
किशोर पाटिल

15

इतना सरल होने का कारण। जावास्क्रिप्ट b = aसंदर्भों का उपयोग करता है, इसलिए जब आप असाइन करते हैं bतो इस प्रकार एक संदर्भ निर्दिष्ट कर रहे हैं जब अपडेट करते हुए aआप अपडेट भी कर रहे हैंb

मुझे यह स्टैकओवरफ्लो पर मिला और भविष्य में इस तरह की चीजों को रोकने में मदद मिलेगी, अगर आप किसी ऑब्जेक्ट की गहरी कॉपी करना चाहते हैं तो इस विधि को कॉल करके।

function clone(obj) {
    // Handle the 3 simple types, and null or undefined
    if (null == obj || "object" != typeof obj) return obj;

    // Handle Date
    if (obj instanceof Date) {
        var copy = new Date();
        copy.setTime(obj.getTime());
        return copy;
    }

    // Handle Array
    if (obj instanceof Array) {
        var copy = [];
        for (var i = 0, len = obj.length; i < len; i++) {
            copy[i] = clone(obj[i]);
        }
        return copy;
    }

    // Handle Object
    if (obj instanceof Object) {
        var copy = {};
        for (var attr in obj) {
            if (obj.hasOwnProperty(attr)) copy[attr] = clone(obj[attr]);
        }
        return copy;
    }

    throw new Error("Unable to copy obj! Its type isn't supported.");
}

धन्यवाद! मैंने एक नया प्रश्न पोस्ट करने से पहले उस पोस्ट को देखा। लेकिन मैं अनिश्चित था कि अगर यह मेरे परिदृश्य में मदद करेगा। यह पता चला कि मुझे क्या चाहिए।
रुटविक गांगुर्ड

सभी नहीं होना चाहिए, लेकिन पहले if (obj instanceof x) { ... }अगर अन्य?
Zac

@Zac इस मामले में नहीं। प्रत्येक इफ-बॉडी (ब्याज की) एक मान लौटाता है। (अगले समारोह से पहले बाहर निकलता है)
Bitterblue

8

मुझे समझ नहीं आता कि उत्तर इतने जटिल क्यों हैं। जावास्क्रिप्ट में, आदिम (तार, संख्या, आदि) मूल्य द्वारा पारित किए जाते हैं, और कॉपी किए जाते हैं। सरणियों सहित ऑब्जेक्ट्स संदर्भ द्वारा पारित किए जाते हैं। किसी भी मामले में, 'ए' से 'बी' नहीं बदलेगा। लेकिन 'ए' की सामग्री को बदलने से 'बी' की सामग्री बदल जाएगी।

var a = 'a'; var b = a; a = 'c'; // b === 'a'

var a = {a:'a'}; var b = a; a = {c:'c'}; // b === {a:'a'} and a = {c:'c'}

var a = {a:'a'}; var b = a; a.a = 'c'; // b.a === 'c' and a.a === 'c'

उपरोक्त पंक्तियों में से किसी एक को (एक बार में) नोड या किसी भी ब्राउज़र जावास्क्रिप्ट कंसोल में पेस्ट करें। फिर कोई भी वैरिएबल टाइप करें और कंसोल यह मान दिखाएगा।


4

तार या इनपुट मूल्यों के लिए आप बस इसका उपयोग कर सकते हैं:

var a = $('#some_hidden_var').val(),
b = a.substr(0);

आप एक आदिम को क्यों प्रतिस्थापित करेंगे? बस इसे असाइन करें, यह स्ट्रिंग को कॉपी करता है। केवल ऑब्जेक्ट, और सरणियाँ (जो ऑब्जेक्ट हैं) संदर्भ द्वारा पारित किए जाते हैं।
ट्रेंटन डी। एडम्स

2

यहां अधिकांश उत्तर अंतर्निहित विधियों का उपयोग कर रहे हैं या पुस्तकालयों / रूपरेखाओं का उपयोग कर रहे हैं। यह सरल विधि ठीक काम करना चाहिए:

function copy(x) {
    return JSON.parse( JSON.stringify(x) );
}

// Usage
var a = 'some';
var b = copy(a);
a += 'thing';

console.log(b); // "some"

var c = { x: 1 };
var d = copy(c);
c.x = 2;

console.log(d); // { x: 1 }

प्रतिभाशाली! अन्य विधियाँ शब्दकोश में सब कुछ बदल देती हैं, जिनमें उनके भीतर सरणियाँ भी शामिल हैं। इसके साथ, मैं ऑब्जेक्ट को क्लोन करता हूं और कंटेंट बरकरार रहता है, इसके विपरीत:Object.assign({},a)
टिक्की

0

मैंने फिलहाल इसे खुद हल कर लिया। मूल मान में केवल 2 उप-गुण होते हैं। मैंने गुणों के साथ एक नई वस्तु का सुधार किया aऔर फिर उसे सौंपा b। अब मेरा ईवेंट हैंडलर केवल अपडेट करता है b, और मेरा मूल aजैसा है वैसा ही रहता है।

var a = { key1: 'value1', key2: 'value2' },
    b = a;

$('#revert').on('click', function(e){
    //FAIL!
    b = a;

    //WIN
    b = { key1: a.key1, key2: a.key2 };
});

यह ठीक काम करता है। मैंने उपरोक्त को छोड़कर अपने कोड में कहीं भी एक लाइन नहीं बदली है, और यह काम करता है कि मैं इसे कैसे चाहता हूं। इसलिए, मेरा विश्वास करो, और कुछ भी अपडेट नहीं हो रहा था a


हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.