2013-03-09 39 views
22

Tôi muốn mở rộng một số thuộc tính đệ quy (còn gọi là bản sao sâu). giống jQuery. Tôi không bao gồm jquery chỉ b/c của một điều.angularjs - mở rộng đệ quy

jQuery.extend(true, target, object1) 

có cách nào thanh lịch mà bạn biết về điều đó với javascript hoặc angularj đơn giản không?

cập nhật xin hãy xem và cố gắng đạt được kết quả tương tự http://plnkr.co/edit/GHabYbyhsqtfBPtplksO?p=preview

tôi đã nhìn vào .copy() nhưng "tài sản (cho các đối tượng) được xóa"

+1

Nhưng bạn chỉ có thể sao chép '$ .extend' từ nguồn jQuery? Đó là [không khó tìm thấy] (https://github.com/jquery/jquery/blob/59232825aa87b941dd2418a6860b64017dfec0ae/src/core.js#L125) và khá độc lập. – Bergi

Trả lời

28

Dưới đây là một chức năng extendDeep dựa tắt của hàm angular.extend. Nếu bạn thêm số này vào phạm vi $ của mình, bạn sẽ có thể gọi

$scope.meta = $scope.extendDeep(ajaxResponse1.myMeta, ajaxResponse2.defaultMeta); 

và nhận câu trả lời bạn đang tìm kiếm.

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

Lưu ý: Chức năng này có tác dụng phụ của việc sao chép các giá trị từ các đối số sau này vào các đối số trước đó. Để sửa lỗi đơn giản cho hiệu ứng phụ này, bạn có thể thay đổi dst[key] = value thành dst[key] = angular.copy(value).

+1

Đó cũng là một giải pháp tốt, mà đội ngũ góc đã làm một cái gì đó như một boolen param đầu tiên (như jquery) – Endless

+0

tôi sẽ đặt nó trong một số chức năng toàn cầu thay vì nghĩ ... – Endless

+0

Đồng ý. Tôi cũng muốn, chỉ muốn chứng minh một cách dễ dàng để làm điều đó bằng cách sử dụng các phương pháp của góc cạnh. –

-1

góc có một phương pháp sao chép:

angular.copy

+1

Giải pháp này xóa nội dung của đích. angular.copy được sử dụng vì một lý do khác với góc cạnh.mở rộng –

+1

-1 'copy()' rất khác với 'extend()' –

+1

Chắc chắn không phải là câu trả lời đúng cho câu hỏi này, nhưng ... câu trả lời này đã giúp tôi đi đúng hướng cho trường hợp cụ thể của tôi. :) –

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

Câu trả lời này chỉ hỗ trợ 2 đối số. Cái của Ryan hỗ trợ nhiều đối số như jQuery.extend, nhưng hãy chắc chắn sử dụng đề xuất của Bennett MeElwee. – user553086

+0

arguments.callee sử dụng được khuyến khích bây giờ -https: //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions_and_function_scope/arguments/callee – chrismarx

1

Xây dựng trên mã của Ryan, bạn có thể rút ngắn kiểm tra đối tượng và bạn cũng KHÔNG nên mở rộng chức năng để bạn không ghi đè con trỏ đối tượng.

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

Các giải pháp giống như Ryan nhưng với sự hỗ trợ cho mảng sáp nhập

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; 
    } 
16

Tất cả các câu trả lời ở đây là hợp lệ cho phiên bản của góc trước 1,4

Tính góc 1.4, bạn có thể sử dụng angular.merge để thực hiện chính xác điều đó:

Không giống như extend(), hợp nhất() đệ quy xuống các thuộc tính đối tượng của đối tượng nguồn, thực hiện bản sao sâu .

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