2013-08-26 11 views
9

आवेदनजावास्क्रिप्ट, संदर्भ खोने

मैं एक सरल वेब अनुप्रयोग है कि AngularJS के शीर्ष पर बनाया गया है पर काम कर रहा हूँ बिना अधिलेखित वस्तु। एप्लिकेशन ऑफलाइन और साथ ही ऑनलाइन काम करने में सक्षम होना चाहिए। जब उपयोगकर्ता ऑफ़लाइन है, तो डेटा में परिवर्तन स्थानीय रूप से संग्रहीत किया जाता है। इसलिए, पहचान-पत्र कि ऑफलाइन मोड में इस एप्लिकेशन के भीतर किया जाता है जब सर्वर पर अपलोड केवल अस्थायी पहचान-पत्र, वे प्रतिस्थापित हो जाता है

समस्या

डेटा है कि आवेदन में उपयोग किया जाता है जटिल वस्तुओं के होते हैं (अन्य वस्तुओं के संबंध/संदर्भ के साथ)। जब मैं सर्वर पर सहेज रहा हूं, तो मैं विचारों को नए "वास्तविक" आईडी के साथ अपडेट करना चाहता था। हालांकि, जावास्क्रिप्ट ऑब्जेक्ट्स के साथ काम करता है क्योंकि संदर्भ मैं ऐसा नहीं कर पा रहा हूं जो मैं चाहता हूं: $scope.data = newdata यह $ scope.data को ओवरराइट नहीं कर रहा है लेकिन एक नई वस्तु बनाता है। पुराने डेटा का पुराना संदर्भ अभी भी वहां है।

सरलीकृत उदाहरण

var x = {id: 1, name: "myObject"} 
var c = x // c = {id: 1, name: "myObject"} 
x = {id: 2, name: "myNewObject"} 
// c = {id: 1, name: "myObject"} 

आप देख सकते हैं, ग अभी भी पुरानी वस्तु के लिए एक संदर्भ है। व्यवहार में, इसका कारण यह है कि मेरा दृश्य नए डेटा के साथ अपडेट नहीं किया गया है क्योंकि यह अभी भी पुराने डेटा से जुड़ा हुआ है। इस उदाहरण में, x के गुणों को ओवरराइट करने के लिए मुझे क्या चाहिए। मुझे यह वास्तविक रूप से करने की ज़रूरत है क्योंकि मेरी असली वस्तुएं जटिल हैं, हालांकि इसे किसी भी परिपत्र संदर्भ में प्रवेश नहीं करना चाहिए, क्योंकि इससे संभवतः ढेर ओवरफ्लो हो सकता है। यदि मैं बी के साथ ओवरराइट कर रहा हूं और इसमें गुण हैं जो बी नहीं मिला है, तो उन गुणों को हटा दिया जाना चाहिए।

क्या मैं ख में

गुणों के साथ

मुझे लगता है कि एक (पुराने वस्तु) में सभी गुण को अधिलेखित करता समारोह के कुछ प्रकार की जरूरत की जरूरत है (नई वस्तु)। सभी गुण जो एक में मौजूद हैं लेकिन बी में नहीं हैं उन्हें हटा दिया जाना चाहिए।

उत्तर

5

मुझे कुछ सोच के बाद समाधान मिला। यह शायद सबसे कुशल समाधान नहीं है, लेकिन यह मेरे लिए नौकरी करता है। समय जटिलता शायद बेहतर हो सकती है, और सुधार के सभी सुझावों का स्वागत है। पहला पैरामीटर ऑब्जेक्ट को विस्तारित किया जाना है, दूसरा वाला विस्तार करने वाला दूसरा। तीसरा एक बूलियन माना जाता है, यह दर्शाता है कि बी में मौजूद गुणों को हटाया जाना चाहिए या नहीं।

function extend(_a,_b,remove){ 
     remove = remove === undefined ? false : remove; 
     var a_traversed = [], 
      b_traversed = []; 

     function _extend(a,b) { 
      if (a_traversed.indexOf(a) == -1 && b_traversed.indexOf(b) == -1){ 
       a_traversed.push(a); 
       b_traversed.push(b); 
       if (a instanceof Array){ 
        for (var i = 0; i < b.length; i++) { 
         if (a[i]){ // If element exists, keep going recursive so we don't lose the references 
          a[i] = _extend(a[i],b[i]); 
         } else { 
          a[i] = b[i]; // Object doesn't exist, no reference to lose 
         } 
        } 
        if (remove && b.length < a.length) { // Do we have fewer elements in the new object? 
         a.splice(b.length, a.length - b.length); 
        } 
       } 
       else if (a instanceof Object){ 
        for (var x in b) { 
         if (a.hasOwnProperty(x)) { 
          a[x] = _extend(a[x], b[x]); 
         } else { 
          a[x] = b[x]; 
         } 
        } 
        if (remove) for (var x in a) { 
         if (!b.hasOwnProperty(x)) { 
          delete a[x]; 
         } 
        } 
       } 
       else{ 
        return b; 
       } 
       return a; 
      }  
     } 

     _extend(_a,_b); 
    } 
4

विधि "का विस्तार" जो अंडरस्कोर और jQuery में उपलब्ध है का उपयोग करना:

//Clear all the 'old' properties from the object 
for (prop in old_object) {delete old_object[prop]} 
//Insert the new ones 
$.extend(old_object, new_object) 
+0

यह सुंदर अत्यधिक आकर्षित है। मैन्युअल रूप से सभी गुणों को लिखता है। – tylerjgarland

1

मैं एक जवाब जोड़ रहा है, भले ही हर किसी को समझाया दोनों क्यों और समाधान किया है।

कारण मैं उत्तर जोड़ रहा हूं, क्योंकि मैंने पिछले कुछ वर्षों में इस उत्तर की खोज की है और हमेशा मूल रूप से उसी 2/3 SO प्रश्नों पर आती है। मैंने समाधान को बहुत कठोर टोकरी में रखा है, क्योंकि जिस कोड के साथ मैं काम कर रहा हूं, उसके पास सभी समान पैटर्न पैटर्न के बाद कई मॉड्यूल हैं; यह आपके द्वारा किए गए एक ही मुद्दे पर उबला हुआ प्रयास करने और हल करने के लिए बहुत अधिक काम रहा है।

जो मैंने सीखा है, और उम्मीद है कि यह अब दूसरों के लिए कुछ मूल्य रखता है कि मैंने वास्तव में इस समस्या से बचने के लिए हमारे कोडबेस को फिर से पहचाना है (कभी-कभी शायद यह अपरिहार्य है, लेकिन कभी-कभी यह निश्चित रूप से होता है) वस्तुओं का संदर्भ देने के लिए 'स्थैतिक निजी चर' का उपयोग करने से बचें।

यह शायद अधिक genericised जा सकता है लेकिन उदाहरण के लिए ले:

var G = { 
    'someKey' : { 
     'foo' : 'bar' 
    } 
}; 

G.MySingletonClass = (function() { 

    var _private_static_data = G.someKey; // referencing an Object 

    return { 

     /** 
     * a method that returns the value of _private_static_data 
     * 
     * @method log 
     **/ 
     log: function() { 

      return _private_static_data; 

     } // eom - log() 

    }; // end of return block 

}()); // end of Class 

console.log(G.MySingletonClass.log()); 

G.someKey = { 
    'baz':'fubar' 
}; 

console.log(G.MySingletonClass.log()); 

http://jsfiddle.net/goxdebfh/1/

आप देख सकते हैं, एक ही समस्या प्रश्नकर्ता द्वारा अनुभवी। मेरे मामले में, और ऑब्जेक्ट्स का संदर्भ देने वाले निजी स्थैतिक चरों का यह उपयोग हर जगह था, मुझे बस अपनी कक्षा के लिए एक सुविधाजनक चर के रूप में संग्रहीत करने के बजाय G.someKey; सीधे देखने की आवश्यकता थी। अंतिम परिणाम (हालांकि असुविधा का एक परिणाम के रूप में लंबे) बहुत अच्छी तरह से काम करता है:

var G = { 
    'someKey' : { 
     'foo' : 'bar' 
    } 
}; 

G.MySingletonClass = (function() { 

    return { 

     /** 
     * a method that returns the value of _private_static_data 
     * 
     * @method log 
     **/ 
     log: function() { 

      return G.someKey; 

     } // eom - log() 

    }; // end of return block 

}()); // end of Class 

console.log(G.MySingletonClass.log()); 

G.someKey = { 
    'baz':'fubar' 
}; 

console.log(G.MySingletonClass.log()); 

http://jsfiddle.net/vv2d7juy/1/

तो, हाँ, शायद कोई नई बात नहीं प्रश्न दिए गए हल किया गया है, लेकिन मुझे लगता है कि साझा करने के लिए क्योंकि मैं मजबूर महसूस किया यह भी मानना ​​था कि पहला उदाहरण चीजों को करने का सही तरीका था। शायद कुछ मामलों में यह निश्चित रूप से नहीं हुआ है।

उम्मीद है कि किसी और को कहीं मदद करता है!

2

अपने वातावरण ECMAScript 2015 का समर्थन करता है, तो आप Object.assign() उपयोग कर सकते हैं:

'use strict' 

let one = { a: 1, b: 2, c: 3 }; 
let two = { b: 20, c: 30, d: 40 }; 

let three = Object.assign({}, one, two); 

console.log(three); 

// will output: Object {a: 1, b: 20, c: 30, d: 40} 

more.. (let ECMAScript 2015 में var के नए स्थानीय रूप से scoped संस्करण है)।


तो अपने सरल उदाहरण के मामले में:

var x = { id: 1, name: "myObject" }; 
Object.assign(x, { id: 2, name: "myNewObject" }); 

console.log(x); 

// will output: Object {id: 2, name: "myNewObject"} 
संबंधित मुद्दे