2010-08-04 10 views
7

JSON verileri için depolama gereksinimlerini, bilinen bir varsayılanlar kümesine göre geliştirerek azaltmak istiyorum. Temelde, istediğim jQuery'nin .extend() fonksiyonu için bir ters aşağıdaki test keyfi JSON uyumlu nesneler için geçmediği şekilde, geçerli:jQuery.extend öğesinin tersi (true,…)

function test_delta(defaults, delta) { 
    var current = $.extend(true, {}, defaults, delta); 

    QUnit.same(get_delta(current, defaults), delta); 
} 

ben yazmaya başlamadan önce benim kendi get_delta(), mevcut bir uygulamasından haberdar kimse var mı?

+0

Bunu kendiniz halletmeniz gerekecek, sert (iç içe döngü) yol. Muhtemelen bildiğin gibi. JSON verileriniz keyfi derinliğe sahipse daha da eğlencelidir. –

+0

Evet, şimdiden bazı ilginç kenar vakaları ile geldim; Bu yüzden "SO oracle" 'e kendim sormadan önce sormam gerektiğini düşündüm. Ah, peki. :-) –

+0

Başlamak için iyi bir yer [jQuery kaynağında] jQuery.fn.extend işlevine bakacaktır (http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.js). – calvinf

cevap

1

Gerçekten aradığınız şey, bir nesne (olası) algoritmasıdır.



function diff (obj1, obj2) { 
    var delta = {}; 

    for (var x in obj1) { 
     if (obj2.hasOwnProperty(x)) { 
      if (typeof obj2[x] == "object") { 
       //recurse nested objects/arrays 
       delta[x] = diff(obj1[x], obj2[x]); 
      } 
      else { 
       //if obj2 doesn't match then - modified attribute 
       if (obj2[x] != obj1[x]) { 
        delta[x] = obj1[x]; 
       } 
      }   
     } 
     else { 
      //obj2 doesn't have this - new attribute 
      delta[x] = obj1[x]; 
     } 
    } 

    return delta; 
} 

alert( 
    JSON.stringify(
    diff({ hello : 'world', gone : 'fishing' }, 
      { hello : 'world' }) 
) 
); 

//outputs: 
{ gone : 'fishing' } 

Bu çok temel bir uygulamasıdır görebileceğiniz gibi - - Eğer ayrı nesnede obj2 eklemeler dönerek tam diferansiyeli sağlamak için bu genişletmek olabilir yazmaya

çok zor değil.

Bu kodda hata yok, nesne prototipleri ve işlevleri farklı tarayıcılarda farklı şekilde ele alınacak, ancak veri yapıları için bir gösteri olarak yeterli olacaktır. Böyle

+0

Kendi kendimi uygulamak için bir bıçak aldım, ancak bunun yerine veritabanı sütununu büyütmeye karar verdiğimiz yeterince açık olmayan kenarlar (özellikle diziler ve silinen özellikler) vardı. –

1

deneyin şey:

jQuery.extend({ 
    deltaExtend: function(deep, target, defaults, delta){ 
     var result = jQuery.extend.apply(jQuery, arguments); 
     jQuery(result).data('delta', delta); 
     jQuery(result).data('defaults', defaults); 
     return result; 
    } 
}); 

kullanımı: Aynı zamanda N nesneler için çalışma elde tweaked olabilir

var result = $.deltaExtend(true, {}, defaults, delta); 
$(result).data('delta') //returns delta object 
$(result).data('defaults') //returns default object 

, sadece biraz daha düşünme gerektirir.

+0

Bu çok ilginç bir fikir! Maalesef, ".extend", "sonuç" nesnesini oluştururken kullanılmıyor, benim durumumda. Bu, her portletin kendi varsayılan ayarlarını tanımlayabileceği bir portal sistemi içindi. "Geçerli" ayarları daha sonra sayfanın ömrü boyunca serbestçe değiştirilecek ve portletin durumunu sunucuya geri getirmek için zaman geldiğinde, depolama gereksinimlerini azaltmak için "kör" bir delta gerçekleştirmeyi umuyordum. –

+0

Aklımda başka bir çözüm var, hangi tarayıcıları destekliyorsunuz ve hangi sürümler daha çok IE'yi destekliyor?

1

Bunun, konu başlatıcısıyla alakalı olması için biraz geç olduğunu biliyorum, ancak Underscore.js adlı _.omit(object, *keys) işlevine bir göz atmak isteyebilirsiniz. Sadece bunu yapar.

+0

Ama "anahtarları" nı biliyorsunuz? – Bergi

+0

Anahtarlar, varsayılanların saklandığı nesneden gelir. '_.keys (defaultObject)' size anahtarlarının bir dizisini verir. – oley

+0

Cevabınızda bunu belirtmeliydin… Ve bu yöntemin sadece * eklenmiş * özellikler için çalıştığını, tüm * değişmiş * olanlar için geçerli olmadığını fark etmelisiniz. – Bergi