2012-06-13 48 views
6

Tôi có hai đối tượng javascript:giá trị loại bỏ mặc định từ một đối tượng

var a = { 
    x: 1, 
    y: { 
     faz: 'hello', 
     baz: '' 
    }, 
    z: [1, 2] 
}; 


var defaults = { 
    x: 2, 
    y: { 
     faz: '', 
     baz: '' 
    }, 
    z: [1, 2] 
}; 

Tôi muốn chỉ giữ các lĩnh vực akhác nhau từ mặc định:

a = remove_defaults(a, defaults); // <---- i need this fnc 
{ 
    x: 1, 
    y: { 
     faz: 'hello' 
    } 
} 

Mục đích là để loại bỏ các giá trị mặc định từ một đối tượng phục vụ như một trạng thái (thông qua URL). Nhà nước có thể có các lĩnh vực lồng nhau, do đó, một so sánh nông là không đủ. Các giá trị lá là tất cả nguyên thủy (số, chuỗi, bool).

(đây là một chút như trái ngược với underscore.js 's _.defaults() phương pháp)

cách tốt nhất để đạt được điều này là gì?


Các giải pháp có thể sử dụng underscore.js nếu giúp, nhưng không có jquery.

+1

Lặp lại đệ quy qua các thuộc tính và so sánh các giá trị của chúng. Không có phương thức tích hợp sẵn. –

Trả lời

3

Hãy thử điều này:

function removeDuplicates(a, defaults, result) { 
    for (var i in a) { 
    if (i in defaults) { 
     if (typeof a[i] == "object" 
      && typeof defaults[i] == "object" 
      && Object.prototype.toString.call(defaults[i]) !== '[object Array]') { 
     result[i] = removeDuplicates(a[i], defaults[i], {}); 
     } else if (a[i] !== defaults[i]) { 
     result[i] = a[i]; 
     } 
    } else { 
     result[i] = a[i]; 
    } 
    } 

    return result; 
} 


var result = removeDuplicates(a, defaults, {}); 
+1

Chúc mừng! Nhưng phần 'a [i] && 'là gì? Điều đó sẽ bỏ qua mọi thứ sai, như 'false',' 0', '''', 'undefined', có vẻ như là một lỗi? – user124114

+1

bạn đã chính xác, tôi đã sửa mã. – ioseb

+0

Ồ, tôi vừa nhận ra có một lỗi lớn ở đó - tất cả các trường được sao chép đều đi đến phạm vi toàn cầu của 'kết quả', thay vì vào các trường con tương ứng của chúng! – user124114

1
function remove_defaults(obj, defaults) { 
    for (var i in obj) { 
    if (typeof obj[i] == 'object') { 
     obj[i] = remove_defaults(obj[i], defaults[i]); 
     continue; 
    } 
    if (defaults[i] !== undefined && obj[i] == defaults[i]) { 
     delete obj[i]; 
    } 
    } 
    return obj; 
} 

Fiddle: http://jsfiddle.net/ybVGq/

+0

Điều này để lại mảng 'z' trong kết quả. Tôi nghĩ rằng giải pháp @ ioseb là tốt hơn, bởi vì điều đó cũng xóa các đối tượng lồng nhau khi chúng hoàn toàn trống rỗng (= tất cả các giá trị bên trong bằng với mặc định). – user124114

+0

Vâng, tôi nhận thấy điều đó. Đó là bởi vì tôi đã sử dụng 'xóa' thay vì tạo một mảng hoàn toàn mới. – jeremyharris

0

mất riêng của tôi:

function no_defaults(obj, defaults) { 
    if ((obj instanceof Array) && (defaults instanceof Array)) { 
     var result = _.difference(obj, defaults); 
     return _.isEmpty(result) ? undefined : result; 
    } 
    if ((obj instanceof Array) || (defaults instanceof Array)) 
     return _.clone(obj); 
    if (typeof obj == "object" && typeof defaults == "object") { 
     var result = {}; 
     for (var prop in obj) { 
      var res = prop in defaults ? no_defaults(obj[prop], defaults[prop]) : _.clone(obj[prop]); 
      if (res !== undefined) 
       result[prop] = res; 
     } 
     return _.isEmpty(result) ? undefined : result; 
    } 
    return _.isEqual(obj, defaults) ? undefined : _.clone(obj); 
} 

Chú giải này sâu quá trình đối tượng, nhưng không phải là mảng. Mảng chỉ được xử lý cho sự khác biệt nông của các phần tử trực tiếp của chúng - nếu các phần tử tự cần no_default, hàm này sẽ không hoạt động. Nhưng điều này là tốt cho trường hợp sử dụng dự định của tôi.

Các vấn đề liên quan