Neden ve ne zaman angular.copy kullanılır? (Derin Kopya)


136

Hizmetlerden alınan tüm verileri doğrudan yerel değişkene, denetleyiciye veya kapsama kaydediyorum. Sanırım sığ bir kopya olarak kabul edilir, doğru mu?

Example:

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

Son zamanlarda derin bir kopya oluşturmak için angular.copy'yi kullanmam söylendi.

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

Ancak, derin kopya bilgileri, Açısal uygulamam tarafından kullanıldığında aynı şekilde çalışıyor gibi görünüyor. Derin bir kopya (angular.copy) kullanmanın belirli yararları var mı ve lütfen bana açıklayabilir misiniz?


2
Nesnenin kopyasına ihtiyacınız varsa angular.copy kullanmanız gerekir (: D). Uax çağrısından ($ http, $ resource, ...) nesne alırsanız, kopyalamaya gerek yoktur. Ancak bu nesneyi görünümde değiştirmek, ancak orijinal nesneyi bir tür önbellekte tutmak istiyorsanız, kopyalamak isteyebilirsiniz.
Petr Averyanov

Yanıtlar:


166

Nesne veya dizinin değerini başka bir değişkene atarken angular.copy kullanın ve bu objectdeğer değiştirilmemelidir.

Derin kopya olmadan veya angular.copy kullanarak , özellik değerini değiştirmek veya yeni bir özellik eklemek , aynı nesneye başvuran tüm nesneleri günceller .

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
Hızlı yanıt için çok teşekkürler, yardımı seviyorum ve anladığımı düşünüyorum. Angular.copy kullanmak için gerçek zaman tam bir kopya olacaktır. Sadece özelliklerini değiştirebileceğim orijinalin bir kopyasına ihtiyacım varsa kullanmalıyım. Bir açısal.copy yapmak yerine bilgileri iki ayrı değişkene kaydedebilir ve özelliklerini ayrı ayrı ayarlayabilir miyim? Örnek: $scope.one = response.datave ayarlayın $scope.two = response.data. Öyleyse yap $scope.two.addProperty = something. Muhtemelen bunu test etmeliyim :) ama topluluk içgörüsü almak isterdim.
Superman2971

2
Cvp: Hayır. Sebep: object propertyGüncelleme yeni değerinin değerinin aynı referansa sahip tüm nesneler için değiştirilmesi . Bu yüzden
angular.copy

44

Bu durumda, kullanmanıza gerek yoktur angular.copy()

Açıklama :

  • =bir referansı temsil ederken angular.copy()derin bir kopya olarak yeni bir nesne oluşturur.

  • Kullanmak =, bir özelliğinin response.datadeğiştirilmesinin karşılık gelen özelliğini değiştireceği anlamına gelir $scope.exampleveya bunun tersi de geçerlidir.

  • angular.copy()İki nesneyi kullanmak ayrı kalır ve değişiklikler birbirini yansıtmaz.


En basit cevap.
Astitva Srivastava

Anlaması en kolay. Teşekkürler
Puneet Verma

7

angular.copy(source);Durumunuzda gereksiz olduğunu söyleyebilirim , eğer daha sonra kullanmazsanız bir hedef olmadan angular.copy(source, [destination]);.

Bir hedef sağlanırsa, tüm öğeleri (diziler için) veya özellikleri (nesneler için) silinir ve ardından kaynaktaki tüm öğeler / özellikler ona kopyalanır.

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


Teşekkürler Esko! Kafamı düz tutmaya çalışıyorum. Bu, angular.copy için bir fayda anlamına gelir mi: bir değişkenin kendisiyle ilişkili veriler varsa, bu, öğeleri / özellikleri yeniden atamanın daha temiz bir yoludur?
Superman2971

1
Sen kullanmak angular.copy()bunu değiştirmeden diğer kod önlemek için bir nesneye. Orijinal nesne değişebilir, ancak kopyanız değişiklikleri görmez. Gerekirse kopyayı eski durumuna getirebilirsiniz.
Esko

1

Angular.copy kullanırken, referansı güncellemek yerine yeni bir nesne oluşturulur ve hedefe atanır (bir hedef sağlanmışsa). Ama dahası da var. Derin bir kopyadan sonra olan bu harika şey var.

Fabrika değişkenlerini güncelleyen yöntemlere sahip bir fabrika hizmetiniz olduğunu varsayalım.

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;
}]);

ve bu servisi kullanan bir kontrolör,

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);
}]);

Yukarıdaki program çalıştırıldığında çıktı aşağıdaki gibi olacaktır,

****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]

Dolayısıyla, açısal kopya kullanmayla ilgili en güzel şey, hedefin referanslarının, değerleri tekrar manuel olarak atamak zorunda kalmadan, değerlerin değişmesiyle yansıtılmasıdır.


1

Zaten cevap verdiğini biliyorum, hala basitleştirmeye çalışıyorum. Yani angular.copy (data), aldığınız nesneyi orijinal değerlerini değiştirmeden / değiştirmeden tutarak değiştirmek / değiştirmek istediğinizde kullanabilirsiniz.

Örneğin: api çağrısı yaptığımı ve originalObj'imi aldığımı varsayalım, şimdi bazı durumlarda api originalObj değerlerini değiştirmek istiyorum ama orijinal değerleri de istiyorum, böylece yapabileceğim şey, api originalObj'm bir kopyasını yapabilirim duplicateObj içinde ve duplicateObj bu şekilde değiştirerek originalObj değerlerim değişmeyecek. Basit bir ifadeyle, dupsateObj modifikasyonu, js objesinin davranış biçiminden farklı olarak originalObj'ye yansır.

 $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);

Sonuç ...

    ----------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

Deneyimlerimi burada paylaşıyorum, iki nesnenin özelliklerini karşılaştırmak için angular.copy () kullandım. Form öğesi olmayan bir dizi giriş üzerinde çalışıyordum, iki nesne özelliğini nasıl karşılaştıracağımı merak ediyordum ve sonuca göre kaydet düğmesini etkinleştirmek ve devre dışı bırakmak zorundayım. Bu yüzden aşağıdaki gibi kullandım.

Kukla nesnesime userCopy demek için özgün bir sunucu nesnesi kullanıcı değerleri atadım ve kullanıcı nesnesindeki değişiklikleri kontrol etmek için saati kullandım.

Sunucudan veri alan sunucu API'm:

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);

Emin değilim ama iki nesneyi karşılaştırmak her zaman benim için baş ağrısıydı ama angular.copy () ile sorunsuz gitti.


-2

Javascript değişkenleri geçer by reference, yani:

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

Şimdi bir by referencekısmı nedeniyle i[1] ve j[1] de ideğişmiş olmasına rağmen . Bunun nedeni, j = ijavascript'in ideğişkeni kopyalamadığını ve değişkene atamadığını jancak ideğişken üzerinden başvurduğunu söylediğimizden kaynaklanır j.

Açısal kopya bu referansı kaybetmemize izin verir, yani:

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

Şimdi iburada [1] 'e, jyine de []' ye eşittir.

Bu tür copyişlevselliğin çok kullanışlı olduğu durumlar vardır .


1
JavaScript nesneleri referans olarak geçirir . İlkel değil. Kodunuzu test edin.
Oleg

Evet iyi fikir oldukça aynı, yine de düzenlenmiş
guramidev

1
Ve angular.copyJSON serileştirmeden daha akıllıdır çünkü işlevlerle başa çıkabilir.
Oleg

bilmiyordum, ben açısal kaynağa bakarak ve sadece JSON serileştirme görmek hatırlıyorum yemin, ama ben tekrar kontrol ve haklısın.
guramidev
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.