2013-03-09 10 views
22

Ich möchte einige Eigenschaften rekursiv erweitern (aka. Tiefe Kopie). ähnlich wie jQuery. Ich schließe Jquery nur b/c von einer Sache ein.angularjs - extend rekursiv

jQuery.extend(true, target, object1) 

Gibt es irgendeine elegante Weise, die Sie wissen, dass es mit einfachem Javascript oder angularjs tut?

Update nehmen Sie bitte einen Blick und versuchen, das gleiche Ergebnis http://plnkr.co/edit/GHabYbyhsqtfBPtplksO?p=preview

i in .copy aussehen zu erreichen(), aber die "Eigenschaften (Objekte) werden gelöscht"

+1

Aber man konnte einfach kopieren '$ .extend' von jQuery-Quelle? Es ist [nicht so schwer zu finden] (https://github.com/jquery/jquery/blob/59232825aa87b941dd2418a6860b64017dfec0ae/src/core.js#L125) und ziemlich eigenständig. – Bergi

Antwort

28

Hier eine extendDeep-Funktion aus der angular.extend Funktion basiert. Wenn Sie dies Ihrem $ -Bereich hinzufügen, können Sie dann

anrufen und erhalten Sie die Antwort, die Sie suchen.

$scope.extendDeep = function extendDeep(dst) { 
    angular.forEach(arguments, function(obj) { 
    if (obj !== dst) { 
     angular.forEach(obj, function(value, key) { 
     if (dst[key] && dst[key].constructor && dst[key].constructor === Object) { 
      extendDeep(dst[key], value); 
     } else { 
      dst[key] = value; 
     }  
     }); 
    } 
    }); 
    return dst; 
}; 

Hinweis: Diese Funktion hat den Nebeneffekt, dass Werte aus späteren Argumenten in die früheren Argumente kopiert werden. Für eine einfache Lösung dieses Nebeneffekts können Sie dst[key] = value in dst[key] = angular.copy(value) ändern.

+1

Das ist auch eine gute Lösung, die eckige Team hatte so etwas getan ein erster param boolen (wie jquery) – Endless

+0

ich würde es in eine globale Funktion statt gedacht denken ... – Endless

+0

Einverstanden. Ich würde auch, wollte nur einen einfachen Weg, um es mit eckigen Methoden zu tun zeigen. –

-1

Angular hat eine Kopiermethode:

angular.copy

+1

Diese Lösung löscht den Inhalt des Ziels. angular.copy wird aus einem anderen Grund als eckig verwendet.extend –

+1

-1 'copy()' ist sehr verschieden von 'extend()' –

+1

Definitiv nicht die richtige Antwort für diese Frage, aber ... diese Antwort half mir in die richtige Richtung für meinen speziellen Fall. :) –

7
function deepExtend(destination, source) { 
    for (var property in source) { 
    if (source[property] && source[property].constructor && 
    source[property].constructor === Object) { 
     destination[property] = destination[property] || {}; 
     arguments.callee(destination[property], source[property]); 
    } else { 
     destination[property] = source[property]; 
    } 
    } 
    return destination; 
} 

Plunker

Src: https://gist.github.com/gregdangelo/2343158

+1

Diese Antwort unterstützt nur 2 Argumente. Der von Ryan unterstützt mehrere Argumente wie jQuery.extend, aber stellen Sie sicher, dass Sie den Vorschlag von Bennett MeElwee verwenden. – user553086

+0

arguments.callee Verwendung wird jetzt abgeraten -https: //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/arguments/callee – chrismarx

1

Aufbauend auf Ryans Code können Sie die Objektprüfung verkürzen und Sie sollten KEINE Funktionen erweitern, so dass Sie keine Objektzeiger überschreiben.

var extendDeep = function extendDeep(dst) { 
    angular.forEach(arguments, function(obj) { 
     if (obj !== dst) { 
      angular.forEach(obj, function(value, key) { 
       if (dst[key] && angular.isObject(dst[key])) { 
        extendDeep(dst[key], value); 
       } else if(!angular.isFunction(dst[key])) { 
        dst[key] = value; 
       } 
      }); 
     } 
    }); 
    return dst; 
}; 
0

Die gleiche Lösung wie Ryan aber mit Unterstützung für Array, die Antworten sind für Versionen von Angular vor 1.4

Ab Angular 1.4, gültig Alle

function extendDeep(dst) { 
     angular.forEach(arguments, function (obj) { 
      if (obj !== dst) { 
      angular.forEach(obj, function (value, key) { 
       if (dst[key] && dst[key].constructor && dst[key].constructor === Object) { 
        extendDeep(dst[key], value); 
       } else if (dst[key] && dst[key].constructor && dst[key].constructor === Array) { 
        dst[key].concat(value); 
       } else if(!angular.isFunction(dst[key])) { 
        dst[key] = value; 
       } 
       } 
      ); 
      } 
     } 
    ); 
     return dst; 
    }