क्यों और कब कोणीय का उपयोग करें? (डीप कॉपी)


136

मैं लोकल वैरिएबल, कंट्रोलर या स्कोप से डायरेक्ट सर्विसेज से प्राप्त सभी डेटा को सेव कर रहा हूँ। मुझे लगता है कि उथली प्रति मानी जाएगी, क्या यह सही है?

Example:

DataService.callFunction()
.then(function(response) {
  $scope.example = response.data;
});

हाल ही में मुझे बताया गया था कि एक गहरी प्रतिलिपि बनाने के लिए कोणीय.कॉपी का उपयोग करें।

$scope.example = angular.copy(response.data);

हालाँकि, गहरी कॉपी जानकारी उसी तरह से काम कर रही है जब मेरे कोणीय अनुप्रयोग द्वारा उपयोग किया जाता है। क्या एक गहरी प्रतिलिपि (angular.copy) का उपयोग करने के लिए विशिष्ट लाभ हैं और क्या आप कृपया मुझे उन्हें समझा सकते हैं?


2
यदि आपको ऑब्जेक्ट की प्रतिलिपि की आवश्यकता है तो यू कोणीय.कोपी का उपयोग करने की आवश्यकता है: (डी)। यदि आप को अजाक्स कॉल ($ http, $ संसाधन, ...) से ऑब्जेक्ट प्राप्त होता है, तो कॉपी करने की कोई आवश्यकता नहीं है। यदि आप इस ऑब्जेक्ट को देखने के लिए संशोधित करना चाहते हैं, लेकिन किसी प्रकार के कैश में मूल ऑब्जेक्ट रखना चाहते हैं, तो आप कॉपी कर सकते हैं।
पेट्र एवरीनोव

जवाबों:


166

किसी अन्य वैरिएबल पर ऑब्जेक्ट या एरे का मान असाइन करते समय कोणीय.कॉपी का उपयोग करें और उस objectमान को परिवर्तित नहीं किया जाना चाहिए।

गहरी कॉपी या एंगुलर.कॉपी का उपयोग किए बिना , संपत्ति का मूल्य बदलना या किसी भी नई संपत्ति को जोड़ना सभी ऑब्जेक्ट को उसी ऑब्जेक्ट को संदर्भित करते हुए अपडेट करता है

var app = angular.module('copyExample', []);
app.controller('ExampleController', ['$scope',
  function($scope) {
    $scope.printToConsole = function() {
      $scope.main = {
        first: 'first',
        second: 'second'
      };

      $scope.child = angular.copy($scope.main);
      console.log('Main object :');
      console.log($scope.main);
      console.log('Child object with angular.copy :');
      console.log($scope.child);

      $scope.child.first = 'last';
      console.log('New Child object :')
      console.log($scope.child);
      console.log('Main object after child change and using angular.copy :');
      console.log($scope.main);
      console.log('Assing main object without copy and updating child');

      $scope.child = $scope.main;
      $scope.child.first = 'last';
      console.log('Main object after update:');
      console.log($scope.main);
      console.log('Child object after update:');
      console.log($scope.child);
    }
  }
]);

// Basic object assigning example

var main = {
  first: 'first',
  second: 'second'
};
var one = main; // same as main
var two = main; // same as main

console.log('main :' + JSON.stringify(main)); // All object are same
console.log('one :' + JSON.stringify(one)); // All object are same
console.log('two :' + JSON.stringify(two)); // All object are same

two = {
  three: 'three'
}; // two changed but one and main remains same
console.log('main :' + JSON.stringify(main)); // one and main are same
console.log('one :' + JSON.stringify(one)); // one and main are same
console.log('two :' + JSON.stringify(two)); // two is changed

two = main; // same as main

two.first = 'last'; // change value of object's property so changed value of all object property 

console.log('main :' + JSON.stringify(main)); // All object are same with new value
console.log('one :' + JSON.stringify(one)); // All object are same with new value
console.log('two :' + JSON.stringify(two)); // All object are same with new value
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="copyExample" ng-controller="ExampleController">
  <button ng-click='printToConsole()'>Explain</button>
</div>


1
त्वरित प्रतिक्रिया के लिए बहुत बहुत धन्यवाद, मदद से प्यार है और मुझे लगता है कि मैं समझता हूं। एंगुलर.कॉपी का उपयोग करने का एकमात्र वास्तविक समय शाब्दिक प्रतिलिपि के लिए होगा। मतलब मुझे केवल इसका उपयोग करना चाहिए अगर मुझे मूल के डुप्लिकेट की आवश्यकता है जिसे मैं गुणों को बदल सकता हूं। क्या मैं सूचना को दो अलग-अलग चरों में सहेज सकता था और एक angular.copy बनाने के बजाय उनके गुणों को अलग-अलग समायोजित कर सकता था? उदाहरण: $scope.one = response.dataऔर सेट $scope.two = response.data। फिर करते हैं $scope.two.addProperty = something। मुझे शायद बस यह परीक्षण करना चाहिए :) लेकिन सामुदायिक अंतर्दृष्टि प्राप्त करना पसंद करेंगे।
सुपरमैन

2
उत्तर: नहीं। कारण: object propertyएक ही संदर्भ वाले सभी ऑब्जेक्ट के लिए अद्यतन नए मूल्य का मूल्य बदलना । इसलिए आपको
Desai

44

उस स्थिति में, आपको उपयोग करने की आवश्यकता नहीं है angular.copy()

स्पष्टीकरण :

  • =एक संदर्भ का प्रतिनिधित्व करता है, जबकि angular.copy()एक गहरी प्रतिलिपि के रूप में एक नई वस्तु बनाता है।

  • उपयोग करने =का अर्थ यह होगा कि संपत्ति response.dataबदलने से $scope.exampleया इसके विपरीत संपत्ति बदल जाएगी ।

  • angular.copy()दो वस्तुओं का उपयोग अलग-अलग रहेगा और परिवर्तन एक दूसरे पर प्रतिबिंबित नहीं होंगे।



सबसे आसान समझने के लिए। धन्यवाद
पुनीत वर्मा

7

मैं कहूंगा कि angular.copy(source);आपकी स्थिति अनावश्यक है यदि बाद में आप इसका उपयोग नहीं करते हैं तो यह बिना गंतव्य के है angular.copy(source, [destination]);

यदि कोई गंतव्य प्रदान किया जाता है, तो इसके सभी तत्व (सरणियों के लिए) या गुण (ऑब्जेक्ट्स के लिए) हटा दिए जाते हैं और फिर स्रोत से सभी तत्वों / गुणों को इसकी प्रतिलिपि बना दी जाती है।

https://docs.angularjs.org/api/ng/function/angular.copy


धन्यवाद Esko! मेरे सिर को सीधा करने की कोशिश कर रहा है। क्या इसका मतलब है कि angular.copy के लिए एक लाभ होगा: यदि एक चर में पहले से ही डेटा जुड़ा हुआ है, तो यह तत्वों / गुणों को पुन: सौंपने का एक क्लीनर तरीका है?
सुपरमैन

1
आप angular.copy()किसी अन्य कोड को संशोधित करने से रोकने के लिए किसी ऑब्जेक्ट का उपयोग करते हैं। मूल वस्तु बदल सकती है, लेकिन आपकी कॉपी में बदलाव नहीं दिखेंगे। जरूरत पड़ने पर आप कॉपी को दोबारा लगा सकते हैं।
एस्को

1

एंगुलर.कॉपी का उपयोग करते समय, संदर्भ को अपडेट करने के बजाय, एक नई वस्तु बनाई जाती है और उसे गंतव्य को सौंपा जाता है (यदि कोई गंतव्य प्रदान किया जाता है)। लेकिन वहाँ अधिक है। यह अच्छी बात है कि एक गहरी नकल के बाद होता है।

मान लें कि आपके पास एक फ़ैक्टरी सेवा है जिसमें विधियाँ हैं जो फ़ैक्टरी चर को अद्यतन करती हैं।

angular.module('test').factory('TestService', [function () {
    var o = {
        shallow: [0,1], // initial value(for demonstration)
        deep: [0,2] // initial value(for demonstration)
    }; 
    o.shallowCopy = function () {
        o.shallow = [1,2,3]
    }
    o.deepCopy = function () {
        angular.copy([4,5,6], o.deep);
    }
    return o;
}]);

और एक नियंत्रक जो इस सेवा का उपयोग करता है,

angular.module('test').controller('Ctrl', ['TestService', function (TestService) {
     var shallow = TestService.shallow;
     var deep = TestService.deep;

     console.log('****Printing initial values');
     console.log(shallow);
     console.log(deep);

     TestService.shallowCopy();
     TestService.deepCopy();

     console.log('****Printing values after service method execution');
     console.log(shallow);
     console.log(deep);

     console.log('****Printing service variables directly');
     console.log(TestService.shallow);
     console.log(TestService.deep);
}]);

जब उपरोक्त कार्यक्रम चलाया जाता है तो आउटपुट निम्नानुसार होगा,

****Printing initial values
[0,1]
[0,2]

****Printing values after service method execution
[0,1]
[4,5,6]

****Printing service variables directly
[1,2,3]
[4,5,6]

इस प्रकार कोणीय प्रतिलिपि का उपयोग करने के बारे में अच्छी बात यह है कि, गंतव्य के संदर्भों को मूल्यों के परिवर्तन के साथ परिलक्षित किया जाता है, बिना मानों को मैन्युअल रूप से पुन: असाइन करने के लिए।


1

मुझे पता है कि इसका पहले से ही उत्तर दिया गया है, फिर भी मैं इसे सरल बनाने की कोशिश कर रहा हूं। तो angular.copy (डेटा) आप उस स्थिति में उपयोग कर सकते हैं जहां आप अपने प्राप्त किए गए ऑब्जेक्ट को उसके मूल मानों को अनमॉडिफ़ाइड / अपरिवर्तित रखते हुए संशोधित / परिवर्तित करना चाहते हैं।

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

 $scope.originalObj={
            fname:'sudarshan',
            country:'India'
        }
        $scope.duplicateObj=angular.copy($scope.originalObj);
        console.log('----------originalObj--------------');
        console.log($scope.originalObj);
        console.log('-----------duplicateObj---------------');
        console.log($scope.duplicateObj);

        $scope.duplicateObj.fname='SUD';
        $scope.duplicateObj.country='USA';
        console.log('---------After update-------')
        console.log('----------originalObj--------------');
        console.log($scope.originalObj);
        console.log('-----------duplicateObj---------------');
        console.log($scope.duplicateObj);

रिजल्ट जैसा है…।

    ----------originalObj--------------
manageProfileController.js:1183 {fname: "sudarshan", country: "India"}
manageProfileController.js:1184 -----------duplicateObj---------------
manageProfileController.js:1185 {fname: "sudarshan", country: "India"}
manageProfileController.js:1189 ---------After update-------
manageProfileController.js:1190 ----------originalObj--------------
manageProfileController.js:1191 {fname: "sudarshan", country: "India"}
manageProfileController.js:1192 -----------duplicateObj---------------
manageProfileController.js:1193 {fname: "SUD", country: "USA"}

1

मैं यहां केवल अपना अनुभव साझा कर रहा हूं, मैंने दो ऑब्जेक्ट्स गुणों की तुलना के लिए angular.copy () का उपयोग किया। मैं फॉर्म एलिमेंट के बिना कई इनपुट्स पर काम कर रहा था, मैं सोच रहा था कि दो ऑब्जेक्ट्स प्रॉपर्टीज की तुलना कैसे करें और परिणाम के आधार पर मुझे सेव बटन को इनेबल और डिसेबल करना होगा। तो मैं नीचे के रूप में इस्तेमाल किया।

मैंने अपनी डमी ऑब्जेक्ट के लिए एक मूल सर्वर ऑब्जेक्ट उपयोगकर्ता मानों को उपयोगकर्ता चॉइस और उपयोगकर्ता ऑब्जेक्ट में परिवर्तनों की जांच करने के लिए घड़ी का उपयोग करने के लिए असाइन किया है।

मेरा सर्वर API जो मुझे सर्वर से डेटा प्राप्त करता है:

var req = {
    method: 'GET',
    url: 'user/profile/' + id,
    headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
}
$http(req).success(function(data) {
    $scope.user = data;
    $scope.userCopy = angular.copy($scope.user);
    $scope.btnSts=true;
}).error(function(data) {
    $ionicLoading.hide();
});

//initially my save button is disabled because objects are same, once something 
//changes I am activating save button

$scope.btnSts = true;
$scope.$watch('user', function(newVal, oldVal) {
    console.log($scope.userCopy.name);

    if ($scope.userCopy.name !== $scope.user.name || $scope.userCopy.email !== $scope.user.email) {
        console.log('Changed');
        $scope.btnSts = false;
    } else {
        console.log('Unchanged');
        $scope.btnSts = true;
    }    
}, true);

मुझे यकीन नहीं है, लेकिन दो वस्तुओं की तुलना करना मेरे लिए वास्तव में सिरदर्द था, लेकिन हमेशा एंगुलर.कॉपी () के साथ यह आसानी से चला गया।


-2

जावास्क्रिप्ट चर चर by reference, इसका मतलब यह है कि:

var i = [];
var j = i;
i.push( 1 );

अब क्योंकि by referenceभाग i[1] है, और j[1] भी है, हालांकि केवल iबदला गया था। ऐसा इसलिए है क्योंकि जब हम कहते हैं कि j = iजावास्क्रिप्ट iवेरिएबल को कॉपी नहीं करता है और इसे असाइन करता है jलेकिन iवेरिएबल को रेफर करता है j

कोणीय प्रतिलिपि हमें इस संदर्भ को खोने देती है, जिसका अर्थ है:

var i = [];
var j = angular.copy( i );
i.push( 1 );

अब iयहाँ [1] के jबराबर है , जबकि अभी भी [] के बराबर है।

ऐसी स्थितियां हैं जब इस तरह की copyकार्यक्षमता बहुत आसान है।


1
जावास्क्रिप्ट वस्तुओं को संदर्भ से गुजरती है । आदिम नहीं। अपने कोड का परीक्षण करें।
ओलेग

हाँ अच्छी तरह से विचार बहुत ही है, हालांकि संपादित
गुरुमीतव

1
और angular.copyJSON सीरियलाइज़ेशन अधिक बुद्धिमान है क्योंकि यह कार्यों से निपट सकता है।
ओलेग

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