2013-06-27 21 views
7

Có cách nào trong javascript để gán giá trị của các trường được đặt tên trong đối tượng vào cùng một trường của đối tượng khác, nếu và chỉ khi trường mục tiêu tồn tại. I E. ghi đè các giá trị cũ, KHÔNG thêm các giá trị mới, bằng cách sử dụng các cấu trúc ideomatic, một lớp lót (đặc biệt cho javascript và/hoặc jQuery) và không có cách nào lặp lại, thậm chí là cả trong.Javascript: Ghi đè CHỈ các trường hiện có trong một đối tượng với các trường khác trong

var theSource = { 
field1: "TEXT", 
field2: "VAL", 
field3: "ZZ", 
field4: "4", 
field5: "5" 
}, 
theTarget = { 
field2: "0", 
field3: "", 
field4: null, 
field5: undefined 
}; 

Something như

var result = jQuery.overwriteOnlyExisting(theTarget, theSource); 
result === { 
field2: "VAL" 
field3: "ZZ" 
... 
} 

NO field1 VÀ lĩnh vực cũ sau field3 được bảo toàn.

jQuery.extend - có thể ghi đè giá trị, nhưng cũng sao chép các trường mới.

Chúng tôi có các tùy chọn nào ở đây?

http://jsbin.com/owivat/1/edit (gạch dưới) - Tôi thích điều này, bây giờ là thời điểm để tìm cách jquery.

Kết quả:

_.extend(theTarget, _(theSource).pick(_(theTarget).keys())); 

142.850 Ops/giây

Object.keys(theTarget).map(function(a) { if (a in theSource) theTarget[a] = theSource[a]; }); 

403.243 Ops/giây

+0

lý do tại sao * ... và không có cách nào lặp lại, ngay cả khi tham gia *? – fcalderan

+2

Bạn nên sử dụng http://underscorejs.org/#each và http://backbonejs.org/#Model-has cho điều đó. Cơ bản là vòng lặp for-in trên nguồn và object.hasOwnProperty trên đích. – inf3rno

+0

@ inf3rno cool để biết, nhưng bị mắc kẹt với jQuery :) –

Trả lời

7

đây là một lót :)

for(var propertyName in theTarget)theTarget[propertyName]&&(theTarget[propertyName]=theSource[propertyName]); 

với underscore.js bạn có thể làm:

_(theTarget).extend(_(theSource).pick(_(theTarget).keys())); 
+1

đó là khái niệm sai của một lớp lót :) một lớp lót được mát mẻ những điều chúng ta có thể làm với bản đồ/mối nối/bộ lọc/regex và cứ thế. Cảm ơn bạn đã làm cho nó hài hước. –

+0

@ gr9zev kiểm tra dấu gạch dưới, thật tuyệt vời cho lập trình hàm –

+0

Xem các nhận xét về OP. Vẫn có thể 'chọn' lấy đối tượng làm tham số? nếu người ta phải tự liệt kê tất cả các trường - đó là điều vô nghĩa. –

5

Bạn có thể làm điều đó bằng tay, tôi không hiểu tại sao "không có vòng". jQuery là looping quá trong một số cách này hay cách khác:

var result = {}; 
for (var key in theSource) { 
    if (theTarget[key]) result[key] = theSource[key]; 
} 
1

Bạn phải đi qua Các phím của source, kiểm tra xem chúng có tồn tại không (nếu chúng không là sự thật vì điều đó sẽ không sao chép trên 0, '', false, null, undefined, NaN) và sao chép giá trị đó vào đối tượng kết quả. Vì bạn không muốn ghi đè lên nguồn hoặc đích, đừng sửa đổi chúng.

jQuery.overwriteOnlyExisting = function (source, target) { 
    var result = {}, key; 
    for (key in target) { 
     result[key] = key in source ? source[key] : target[key]; 
    } 
    return result 
}; 
+0

điểm hợp lệ, đó là lý do tại sao tôi cố gắng dựa vào nhiều công phu hơn cơ chế của js và jquery, không để đi vào một cái bẫy của 'quên cái gì đó'. –

3

OK! lót! không có vòng lặp nhìn thấy được!

Object.keys(theTarget).map(function(a){ if(theSource[a]) theTarget[a]=theSource[a]}) 

Mặc dù bản đồ có vòng lặp trong nguồn của nó, tôi chắc chắn. nhưng tôi nghĩ đây là cách duy nhất để làm điều đó mà không có cấu trúc vòng lặp nhìn thấy được. mặc dù nó lạm dụng không gian tên chung của javascript và do đó bị bẩn.

Được rồi, thậm chí tốt hơn:

Object.keys(theTarget).map(function(a){ if(Object.keys(theSource).indexOf(a)) theTarget[a]=theSource[a]}) 

và súc tích hơn

keys(theTarget).map(function(a){ if(a in theSource) theTarget[a]=theSource[a]}) 

dù phím() và Mảng # indexOf wont work trong các phiên bản ECMA cũ.

+0

Nó tốt hơn, nhưng tôi đã thấy phép thuật js, phải là một số kiểm tra tích hợp cho 'if (theSource [a])'. Cộng với tâm trí câu trả lời của Poetro, giải pháp này sẽ không làm việc với các nguồn [a] === '', 0, null và như vậy –

+1

ok, đây là một tốt hơn. Mảng # indexOf sẽ hoạt động hoàn hảo. –

+0

Tôi không nghĩ rằng điều này có thể được tái cấu trúc lại ngắn gọn hơn. –

1
var theSource = { 
field1: "TEXT", 
field2: "VAL", 
field3: "ZZ", 
field4: "4", 
field5: "5" 
}, 
theTarget = { 
field2: "0", 
field3: "", 
field4: null, 
field5: undefined 
}; 

var overrideExistingProperties = function (theTarget, theSource){ 
    for (var property in theSource) 
     if (theSource.hasOwnProperty(property) && theTarget.hasOwnProperty(property)) 
      theTarget[property] = theSource[property]; 
}; 

overrideExistingProperties(theTarget, theSource); 
result = theTarget; //if you don't want to clone 
Các vấn đề liên quan