ES6 WeakMap के वास्तविक उपयोग क्या हैं?


397

के वास्तविक उपयोग क्या हैं WeakMapECMAScript 6 में पेश किए डेटा संरचना ?

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

यह मुझे लगता है कि यह:

weakmap.set(key, value);

... यह कहने का सिर्फ एक गोल चक्कर है:

key.value = value;

मुझे कौन से ठोस उपयोग के मामले याद आ रहे हैं?




35
वास्तविक विश्व उपयोग का मामला: DOM नोड के लिए कस्टम डेटा संग्रहीत करें।
फेलिक्स क्लिंग

कमजोर संदर्भों के लिए आपके द्वारा उपयोग किए जाने वाले सभी मामले सुपर महत्वपूर्ण भी हैं। वे भाषा को जोड़ने के लिए सिर्फ एक बहुत कठिन हैं क्योंकि वे nondeterminism का परिचय देते हैं। मार्क मिलर और अन्य लोगों ने कमजोर संदर्भों पर बहुत काम किया है और मुझे लगता है कि वे अंततः आ रहे हैं। आखिरकार
बेंजामिन Gruenbaum

2
WeakMap: स्मृति रिसाव का पता लगाने के लिए इस्तेमाल किया जा सकता stevehanov.ca/blog/?id=148
theWebalyst

जवाबों:


513

मूलरूप में

WeakMaps कचरा संग्रहण में हस्तक्षेप किए बिना बाहर से वस्तुओं का विस्तार करने का एक तरीका प्रदान करता है। जब भी आप किसी ऑब्जेक्ट को विस्तारित करना चाहते हैं, लेकिन ऐसा नहीं कर सकते क्योंकि यह सील है - या एक बाहरी स्रोत से - एक कमजोर नक्शा लागू किया जा सकता है।

WeakMap एक नक्शा (शब्दकोश) है जहाँ कुंजियाँ कमज़ोर होती हैं - अर्थात, यदि कुंजी के सभी संदर्भ खो गए हैं और मूल्य के लिए अधिक संदर्भ नहीं हैं - मान एकत्र किया जा सकता है। आइए इसे पहले उदाहरणों के माध्यम से दिखाएं, फिर इसे थोड़ा समझाएं और अंत में वास्तविक उपयोग के साथ समाप्त करें।

मान लीजिए कि मैं एक एपीआई का उपयोग कर रहा हूं जो मुझे एक निश्चित वस्तु देता है:

var obj = getObjectFromLibrary();

अब, मेरे पास एक तरीका है जो ऑब्जेक्ट का उपयोग करता है:

function useObj(obj){
   doSomethingWith(obj);
}

मैं इस बात का ध्यान रखना चाहता हूं कि किसी निश्चित ऑब्जेक्ट के साथ विधि को कितनी बार बुलाया गया था और यदि यह N से अधिक बार होता है तो रिपोर्ट करें। मानचित्र का उपयोग करने के लिए कोई भी व्यक्ति सोचता है:

var map = new Map(); // maps can have object keys
function useObj(obj){
    doSomethingWith(obj);
    var called = map.get(obj) || 0;
    called++; // called one more time
    if(called > 10) report(); // Report called more than 10 times
    map.set(obj, called);
}

यह काम करता है, लेकिन इसकी मेमोरी लीक होती है - हम अब फंक्शन में पास की गई हर एक लाइब्रेरी ऑब्जेक्ट पर नज़र रखते हैं, जो लाइब्रेरी ऑब्जेक्ट्स को कभी भी कचरा इकट्ठा होने से बचाए रखता है। इसके बजाय - हम एक का उपयोग कर सकते हैं WeakMap:

var map = new WeakMap(); // create a weak map
function useObj(obj){
    doSomethingWith(obj);
    var called = map.get(obj) || 0;
    called++; // called one more time
    if(called > 10) report(); // Report called more than 10 times
    map.set(obj, called);
}

और मेमोरी लीक हो गया है।

बक्सों का इस्तेमाल करें

कुछ उपयोग के मामले जो अन्यथा स्मृति रिसाव का कारण बनेंगे और WeakMapएस द्वारा सक्षम हैं:

  • किसी विशिष्ट वस्तु के बारे में निजी डेटा रखना और केवल मैप के संदर्भ में लोगों को उस तक पहुंच प्रदान करना। अधिक-तदर्थ दृष्टिकोण निजी-प्रतीकों के प्रस्ताव के साथ आ रहा है लेकिन अब से एक लंबा समय है।
  • उन्हें बदलने या ओवरहेड किए बिना लाइब्रेरी ऑब्जेक्ट्स के बारे में डेटा रखना।
  • वस्तुओं के एक छोटे से समूह के बारे में डेटा रखना जहां प्रकार की कई वस्तुएं छिपी हुई कक्षाओं के साथ समस्याएं पैदा नहीं करती हैं जेएस इंजन एक ही प्रकार की वस्तुओं के लिए उपयोग करते हैं।
  • ब्राउज़र में होस्ट नोड जैसी होस्ट ऑब्जेक्ट के बारे में डेटा रखना।
  • बाहर से किसी वस्तु की क्षमता जोड़ना (जैसे अन्य उत्तर में घटना का उदाहरण)।

आइए एक वास्तविक उपयोग को देखें

इसका उपयोग बाहर से किसी वस्तु का विस्तार करने के लिए किया जा सकता है। आइए Node.js. की वास्तविक दुनिया से एक व्यावहारिक (अनुकूलित, वास्तविक प्रकार - एक बिंदु बनाने के लिए) उदाहरण दें।

मान लीजिए कि आप Node.js हैं और आपके पास Promiseऑब्जेक्ट्स हैं - अब आप वर्तमान में अस्वीकार किए गए सभी वादों पर नज़र रखना चाहते हैं - हालाँकि, आप उन्हें कचरा एकत्र होने से नहीं रखना चाहते हैं, क्योंकि उनके लिए कोई संदर्भ मौजूद नहीं है।

अब, आप स्पष्ट कारणों के लिए देशी वस्तुओं में गुण जोड़ना नहीं चाहते हैं - इसलिए आप फंस गए हैं। यदि आप उन वादों के संदर्भ रखते हैं जो आपके द्वारा मेमोरी रिसाव का कारण बन रहे हैं क्योंकि कोई कचरा संग्रह नहीं हो सकता है। यदि आप संदर्भ नहीं रखते हैं तो आप व्यक्तिगत वादों के बारे में अतिरिक्त जानकारी नहीं बचा सकते हैं। कोई भी योजना जिसमें वादे की आईडी को सहेजना निहित है, इसका मतलब है कि आपको इसके संदर्भ की आवश्यकता है।

WeakMaps दर्ज करें

WeakMaps का मतलब है कि चाबियाँ कमजोर हैं। एक कमजोर नक्शे की गणना करने या उसके सभी मूल्यों को प्राप्त करने के लिए कोई उपाय नहीं हैं। एक कमजोर मानचित्र में, आप एक कुंजी के आधार पर डेटा को स्टोर कर सकते हैं और जब कुंजी कचरा एकत्र करती है तो मानों को इकट्ठा करते हैं।

इसका मतलब यह है कि एक वादा दिया गया है कि आप इसके बारे में राज्य को स्टोर कर सकते हैं - और वह वस्तु अभी भी कचरा एकत्र किया जा सकता है। बाद में, यदि आपको किसी ऑब्जेक्ट का संदर्भ मिलता है, तो आप जांच सकते हैं कि क्या आपके पास इससे संबंधित कोई राज्य है और इसकी रिपोर्ट करें।

इसका उपयोग पेट्का एंटोनोव द्वारा इस तरह से अनहेल्ड रिजेक्शन हुक को लागू करने के लिए किया गया था :

process.on('unhandledRejection', function(reason, p) {
    console.log("Unhandled Rejection at: Promise ", p, " reason: ", reason);
    // application specific logging, throwing an error, or other logic here
});

हम एक नक्शे में वादों के बारे में जानकारी रखते हैं और यह पता कर सकते हैं कि खारिज किए गए वादे को कब संभाला गया।


8
नमस्कार! क्या आप कृपया मुझे बता सकते हैं कि कोड का कौन सा भाग मेमोरी लीक का कारण बनता है?
ltamajs

15
@ ltamajs4 यकीन है, useObjउदाहरण में, हम एक नक्शा कुंजी के रूप में पारित वस्तु का उपयोग Mapनहीं WeakMapकरते हैं। ऑब्जेक्ट को मानचित्र से कभी भी हटाया नहीं जाता है (क्योंकि हम नहीं जानते कि ऐसा कब करना है) इसलिए हमेशा इसका संदर्भ होता है और इसे कभी भी एकत्र नहीं किया जा सकता है। WeakMap उदाहरण में जैसे ही ऑब्जेक्ट के अन्य सभी संदर्भ चले गए हैं - ऑब्जेक्ट को से साफ़ किया जा सकता है WeakMap। यदि आप अभी भी निश्चित नहीं हैं कि मेरा क्या मतलब है तो कृपया मुझे बताएं
बेंजामिन ग्रुएनबाम

@ बैंजामिन, हमें मेमोरी-संवेदी कैश की आवश्यकता और डेटा_ओबजेक्ट टपल की आवश्यकता के बीच अंतर करना होगा। इन दो अलग-अलग आवश्यकताओं का सामना न करें। आपका calledउदाहरण jsfiddle.net/f2efbm7z का उपयोग करके बेहतर लिखा गया है और यह एक कमजोर मानचित्र के उपयोग को प्रदर्शित नहीं करता है। वास्तव में, यह कुल 6 तरीकों से लिखा जा सकता है, जिन्हें मैं नीचे सूचीबद्ध करूंगा।
पचेरियर

मौलिक रूप से, कमजोर मानचित्र का उद्देश्य स्मृति-संवेदी कैश है। जबकि इसका उपयोग बाहर से वस्तुओं का विस्तार करने के लिए किया जा सकता है, यह एक अनिच्छुक घटिया हैक है और निश्चित रूप से इसका उचित उद्देश्य नहीं है
पचेरियर

1
यदि आप किसी वादे के बीच की कड़ी रखना चाहते हैं और इसे कितनी बार संभाला / अस्वीकार किया गया है, तो 1) प्रतीक का उपयोग करें ; p[key_symbol] = data। या 2) अद्वितीय नामकरण; p.__key = data। या 3) निजी गुंजाइश; (()=>{let data; p.Key = _=>data=_;})()। या 4) 1 या 2 या 3. या 5 के साथ प्रॉक्सी ) 1 या 2 या 3. या 6 के साथ वादा वर्ग का स्थान बदलें / विस्तार करें / आवश्यक सदस्यों के एक टपल के साथ वादा वर्ग का विस्तार / विस्तार करें। - किसी भी मामले में, कमजोर मानचित्र की आवश्यकता नहीं है जब तक कि आपको मेमोरी संवेदनशील कैश की आवश्यकता न हो।
पचेरियर

48

यह उत्तर वास्तविक दुनिया के परिदृश्य में पक्षपाती और अनुपयोगी लगता है। कृपया इसे पढ़ें और प्रयोग के अलावा किसी अन्य चीज़ के लिए इसे वास्तविक विकल्प न मानें

एक उपयोग मामला श्रोताओं के लिए एक शब्दकोश के रूप में उपयोग करने के लिए हो सकता है, मेरे पास एक सहकर्मी है जिसने ऐसा किया है। यह बहुत सहायक है क्योंकि किसी भी श्रोता को चीजों को करने के इस तरीके से सीधे लक्षित किया जाता है। अलविदाlistener.on

लेकिन अधिक सार बिंदु से, WeakMapविशेष रूप से मूल रूप से कुछ भी करने के लिए पहुंच को नष्ट करने के लिए विशेष रूप से शक्तिशाली है, आपको अपने सदस्यों को अलग करने के लिए नामस्थान की आवश्यकता नहीं है क्योंकि यह पहले से ही इस संरचना की प्रकृति से निहित है। मुझे पूरा यकीन है कि आप अजीबोगरीब निरर्थक वस्तु कुंजियों को बदलकर कुछ बड़े स्मृति सुधार कर सकते हैं (भले ही डिकॉन्स्ट्रक्टिंग आपके लिए काम करता हो)।


आगे क्या है पढ़ने से पहले

मुझे अब एहसास हुआ कि मेरा जोर देना समस्या से निपटने का सबसे अच्छा तरीका नहीं है और जैसा कि बेंजामिन ग्रुएनबाम ने बताया (उनके जवाब की जांच करें, अगर यह पहले से ही मेरा नहीं है: पी), तो यह समस्या एक नियमित रूप से हल नहीं हो सकती थी Map, क्योंकि यह लीक हो जाएगा, इस प्रकार मुख्य ताकत WeakMapयह है कि यह कचरा संग्रह में हस्तक्षेप नहीं करता है, क्योंकि वे एक संदर्भ नहीं रखते हैं।


यहाँ मेरे सहकर्मी का वास्तविक कोड है ( उसके लिए धन्यवाद साझा )

पूर्ण स्रोत यहां है , यह श्रोताओं के प्रबंधन के बारे में है जिसके बारे में मैंने ऊपर बात की थी (आप चश्मा भी देख सकते हैं )

var listenableMap = new WeakMap();


export function getListenable (object) {
    if (!listenableMap.has(object)) {
        listenableMap.set(object, {});
    }

    return listenableMap.get(object);
}


export function getListeners (object, identifier) {
    var listenable = getListenable(object);
    listenable[identifier] = listenable[identifier] || [];

    return listenable[identifier];
}


export function on (object, identifier, listener) {
    var listeners = getListeners(object, identifier);

    listeners.push(listener);
}


export function removeListener (object, identifier, listener) {
    var listeners = getListeners(object, identifier);

    var index = listeners.indexOf(listener);
    if(index !== -1) {
        listeners.splice(index, 1);
    }
}


export function emit (object, identifier, ...args) {
    var listeners = getListeners(object, identifier);

    for (var listener of listeners) {
        listener.apply(object, args);
    }
}

2
मुझे इस बारे में कुछ पता नहीं है कि आप इसका उपयोग कैसे करेंगे। यह देखने योग्य होगा कि जब कोई संदर्भ न हो तो उससे जुड़ी घटनाओं के साथ इसका पतन हो जाए। समस्या यह है कि जब ऑब्जर्वर को अब संदर्भित नहीं किया जाता है। मुझे लगता है कि यहां समाधान केवल आधी समस्या का हल है। मुझे नहीं लगता कि आप WeakMap के साथ पर्यवेक्षक समस्या को हल कर सकते हैं क्योंकि यह चलने योग्य नहीं है।
14:15 बजे jgmjgm

1
डबल-बफ़रिंग इवेंट श्रोता अन्य भाषाओं में तेज़ हो सकते हैं, लेकिन इस मामले में यह केवल सादा गूढ़ और धीमा है। वह मेरा तीन-सेंट है।
जैक गिफिन

@axelduch, वाह इस श्रोता-संभाल मिथक को जावास्क्रिप्ट समुदाय के लिए सभी तरह से पेड कर दिया गया है, 40 अपवोट्स प्राप्त कर रहा है! यह समझने के लिए कि यह उत्तर पूरी तरह से गलत क्यों है , देखें stackoverflow.com/ के
156618/632951

1
@ स्पेसर ने उत्तर को अपडेट किया, प्रतिक्रिया के लिए धन्यवाद
axelduch

1
@axelduch, हाँ, वहाँ से भी एक रेफरी है।
पचेरियर

18

WeakMap एन्कैप्सुलेशन और सूचना छिपाने के लिए अच्छी तरह से काम करता है

WeakMapकेवल ES6 और इसके बाद के संस्करण के लिए उपलब्ध है। A WeakMapकुंजी और मान युग्मों का एक संग्रह है जहाँ कुंजी को एक वस्तु होना चाहिए। निम्नलिखित उदाहरण में, हम WeakMapदो वस्तुओं के साथ निर्माण करते हैं :

var map = new WeakMap();
var pavloHero = {first: "Pavlo", last: "Hero"};
var gabrielFranco = {first: "Gabriel", last: "Franco"};
map.set(pavloHero, "This is Hero");
map.set(gabrielFranco, "This is Franco");
console.log(map.get(pavloHero));//This is Hero

हमने set()किसी वस्तु और किसी अन्य वस्तु (हमारे मामले में एक स्ट्रिंग) के बीच संबंध को परिभाषित करने के लिए विधि का उपयोग किया । हमने get()किसी ऑब्जेक्ट से जुड़े आइटम को पुनः प्राप्त करने के लिए विधि का उपयोग किया । एस का दिलचस्प पहलू WeakMapयह है कि यह मानचित्र के अंदर की के लिए एक कमजोर संदर्भ रखता है। एक कमजोर संदर्भ का मतलब है कि यदि वस्तु नष्ट हो जाती है, तो कचरा कलेक्टर पूरी प्रविष्टि को हटा देगा WeakMap, इस प्रकार स्मृति को मुक्त कर देगा।

var TheatreSeats = (function() {
  var priv = new WeakMap();
  var _ = function(instance) {
    return priv.get(instance);
  };

  return (function() {
      function TheatreSeatsConstructor() {
        var privateMembers = {
          seats: []
        };
        priv.set(this, privateMembers);
        this.maxSize = 10;
      }
      TheatreSeatsConstructor.prototype.placePerson = function(person) {
        _(this).seats.push(person);
      };
      TheatreSeatsConstructor.prototype.countOccupiedSeats = function() {
        return _(this).seats.length;
      };
      TheatreSeatsConstructor.prototype.isSoldOut = function() {
        return _(this).seats.length >= this.maxSize;
      };
      TheatreSeatsConstructor.prototype.countFreeSeats = function() {
        return this.maxSize - _(this).seats.length;
      };
      return TheatreSeatsConstructor;
    }());
})()

4
"अतिक्रमण और सूचना छुपाने के लिए दुर्बलता अच्छी तरह से काम करती है"। सिर्फ इसलिए कि आप कर सकते हैं, इसका मतलब यह नहीं है कि आपको चाहिए। जावास्क्रिप्ट में एनकैप्सुलेशन करने और डिफॉल्ट करने से पहले जानकारी छिपाने के तरीके भी डिफ़ॉल्ट हैं। अभी तक, इसे करने के 6 तरीके हैं । अतिक्रमण करने के लिए दुर्बलता का उपयोग करना एक बदसूरत चेहरा है।
पचेरियर

12

𝗠𝗲𝘁𝗮𝗱𝗮𝘁𝗮

कमजोर मैप्स का इस्तेमाल मेटाडेटा को स्टोर करने के लिए किया जा सकता है, जो बिना कूड़ा कलेक्शन में दखल दिए या आपके कोड के सहकर्मियों को पागल बना सकता है। उदाहरण के लिए, आप उन्हें एक वेबपेज में सभी तत्वों को संख्यात्मक सूचकांक में उपयोग कर सकते हैं।

𝗼𝗿 𝗼𝗿 𝗪𝗶𝘁𝗵𝗼𝘂𝘁 𝗼𝗿:

var elements = document.getElementsByTagName('*'),
  i = -1, len = elements.length;

while (++i !== len) {
  // Production code written this poorly makes me want to cry:
  elements[i].lookupindex = i;
  elements[i].elementref = [];
  elements[i].elementref.push( elements[(i * i) % len] );
}

// Then, you can access the lookupindex's
// For those of you new to javascirpt, I hope the comments below help explain 
// how the ternary operator (?:) works like an inline if-statement
document.write(document.body.lookupindex + '<br />' + (
    (document.body.elementref.indexOf(document.currentScript) !== -1)
    ? // if(document.body.elementref.indexOf(document.currentScript) !== -1){
    "true"
    : // } else {
    "false"
  )   // }
);

𝗮𝗻𝗱 𝗮𝗻𝗱 𝗨𝘀𝗶𝗻𝗴 𝗮𝗻𝗱:

var DOMref = new WeakMap(),
  __DOMref_value = Array,
  __DOMref_lookupindex = 0,
  __DOMref_otherelement = 1,
  elements = document.getElementsByTagName('*'),
  i = -1, len = elements.length, cur;

while (++i !== len) {
  // Production code written this greatly makes me want to 😊:
  cur = DOMref.get(elements[i]);
  if (cur === undefined)
    DOMref.set(elements[i], cur = new __DOMref_value)

  cur[__DOMref_lookupindex] = i;
  cur[__DOMref_otherelement] = new WeakSet();
  cur[__DOMref_otherelement].add( elements[(i * i) % len] );
}

// Then, you can access the lookupindex's
cur = DOMref.get(document.body)
document.write(cur[__DOMref_lookupindex] + '<br />' + (
    cur[__DOMref_otherelement].has(document.currentScript)
    ? // if(cur[__DOMref_otherelement].has(document.currentScript)){
    "true"
    : // } else {
    "false"
  )   // }
);

𝗧𝗵𝗲 𝗧𝗵𝗲

अंतर नगण्य दिख सकता है, इस तथ्य से अलग कि कमजोर संस्करण लंबा है, हालांकि ऊपर दिखाए गए कोड के दो टुकड़ों के बीच एक बड़ा अंतर है। कोड के पहले स्निपेट में, कमजोर नक्शों के बिना, कोड का टुकड़ा DOM तत्वों के बीच हर तरह से संदर्भ देता है। यह DOM तत्वों को कचरा एकत्र होने से रोकता है।(i * i) % lenएक ऑडबॉल की तरह लग सकता है जो कोई भी उपयोग नहीं करेगा, लेकिन फिर से सोचें: बहुत सारे उत्पादन कोड में डोम संदर्भ होते हैं जो दस्तावेज़ पर सभी उछाल देते हैं। अब, कोड के दूसरे टुकड़े के लिए, क्योंकि तत्वों के सभी संदर्भ कमजोर हैं, जब आप एक नोड को हटाते हैं, तो ब्राउज़र यह निर्धारित करने में सक्षम होता है कि नोड का उपयोग नहीं किया गया है (आपके कोड तक पहुंचने में सक्षम नहीं है), और इस प्रकार इसे मेमोरी से हटा दें। आपको मेमोरी के उपयोग और मेमोरी एंकर के बारे में चिंता क्यों करनी चाहिए इसका कारण (कोड के पहले स्निपेट जैसे कि अप्रयुक्त तत्वों को मेमोरी में रखा जाता है) क्योंकि अधिक मेमोरी उपयोग का अर्थ है अधिक ब्राउज़र जीसी-प्रयास (मेमोरी को खाली करने की कोशिश करना) औसत ब्राउज़र क्रैश) का अर्थ है धीमी ब्राउज़िंग अनुभव और कभी-कभी ब्राउज़र क्रैश।

इन के लिए एक पॉलीफ़िल के रूप में, मैं अपनी खुद की लाइब्रेरी ( यहाँ पाया गया @ github ) की सिफारिश करेगा । यह एक बहुत ही हल्की लाइब्रेरी है जो किसी भी तरह से बिना जटिल-जटिल ढांचे के पॉलीफ़िल करेगा जो आपको अन्य पॉलीफ़िल में मिल सकता है।

~ हैप्पी कोडिंग!


1
स्पष्ट स्पष्टीकरण के लिए धन्यवाद। एक उदाहरण किसी भी शब्द से अधिक लायक है।
newguy 4

@lolzery, रे " यह रोकता कचरा जा रहा एकत्र से डोम तत्वों ", आप सभी की जरूरत है सेट elementsअशक्त करने के लिए और बस हो गया: यह GCed हो जाएगा। & पुनः " DOM संदर्भ जो दस्तावेज़ में सभी को उछालता है ", बिल्कुल भी मायने नहीं रखता है: एक बार मुख्य लिंक elementsचले जाने के बाद, सभी परिपत्र रेफरी GCed हो जाएंगे। यदि आपका तत्व उस तत्व के संदर्भ में पकड़ रहा है जिसकी उसे आवश्यकता नहीं है, तो कोड को ठीक करें और रेफरी को शून्य पर सेट करें जब आप इसका उपयोग कर रहे हों। यह GCed हो जाएगा। कमजोरों की जरूरत नहीं है
पचेरियर

2
@Pacerier ने आपके उत्साही फीडबैक के लिए धन्यवाद दिया, हालाँकि elementsअशक्त करने के लिए सेटिंग ब्राउज़र को पहले स्निप स्थिति में GC को तत्वों की अनुमति नहीं देगा। ऐसा इसलिए है क्योंकि आप तत्वों पर कस्टम गुण सेट करते हैं, और फिर वे तत्व अभी भी प्राप्त किए जा सकते हैं, और उनके कस्टम गुण अभी भी एक्सेस किए जा सकते हैं, इस प्रकार उनमें से किसी को भी GC'ed होने से रोका जा सकता है। इसे धातु के छल्ले की एक श्रृंखला की तरह समझें। सोलंगस आपके पास श्रृंखला में कम से कम एक लिंक तक पहुंच है, आप श्रृंखला में उस लिंक पर पकड़ कर सकते हैं, और इस प्रकार आइटम की पूरी श्रृंखला को रसातल में गिरने से रोक सकते हैं।
जैक गिफिन

1
नाम के साथ डंडर के साथ उत्पादन कोड मुझे उल्टी कर देता है
बारू बारबु

10

मैं उन WeakMapकार्यों के चिंता मुक्त संस्मरण के कैश का उपयोग करता हूं जो अपरिवर्तनीय वस्तुओं को उनके पैरामीटर के रूप में लेते हैं।

संस्मरण कहने का फैंसी तरीका है "मूल्य की गणना करने के बाद, इसे कैश करें ताकि आपको इसे फिर से गणना करने की आवश्यकता न हो"।

यहाँ एक उदाहरण है:

ध्यान देने योग्य कुछ बातें:

  • Immutable.js ऑब्जेक्ट्स नई ऑब्जेक्ट्स (एक नए पॉइंटर के साथ) वापस करते हैं जब आप उन्हें संशोधित करते हैं तो उन्हें WeakMap में कुंजियों के रूप में उपयोग करके उसी गणना किए गए मान की गारंटी होती है।
  • WeakMap मेमो के लिए बहुत अच्छा है क्योंकि एक बार ऑब्जेक्ट (कुंजी के रूप में उपयोग किया जाता है) कचरा एकत्र हो जाता है, इसलिए WeakMap पर गणना मूल्य होता है।

1
यह कमज़ोर उपयोग का एक वैध उपयोग है जब तक कि संस्मरण कैश मेमोरी-सेंसिटिव होने का मतलब है , पूरे ओज / फ़ंक्शन जीवन में लगातार नहीं। यदि "मेमोइज़ेशन कैश" का अर्थ है ओबज / फ़ंक्शन जीवन में लगातार रहना है, तो कमज़ोर गलत विकल्प है: इसके बजाय 6 डिफ़ॉल्ट जावास्क्रिप्ट एनकैप्सुलेशन तकनीकों में से किसी का उपयोग करें ।
पचेरियर

3

WeakMaps के लिए मेरे पास यह सरल सुविधा आधारित उपयोग मामला / उदाहरण है।

उपयोगकर्ताओं का एक संग्रह

मैं एक के साथ शुरुआत की Userवस्तु जिसका गुण एक में शामिल हैं fullname, username, age, genderऔर एक विधि कहा जाता हैprint जो अन्य संपत्तियों के एक मानव पठनीय सारांश प्रिंट करता है।

/**
Basic User Object with common properties.
*/
function User(username, fullname, age, gender) {
    this.username = username;
    this.fullname = fullname;
    this.age = age;
    this.gender = gender;
    this.print = () => console.log(`${this.fullname} is a ${age} year old ${gender}`);
}

मैंने तब usersकई उपयोगकर्ताओं का एक संग्रह रखने के लिए एक मानचित्र जोड़ा , जिसके द्वारा कुंजीबद्ध हैंusername

/**
Collection of Users, keyed by username.
*/
var users = new Map();

संग्रह को जोड़ने के लिए भी सहायक कार्यों को जोड़ना, प्राप्त करना, एक उपयोगकर्ता को हटाना और यहां तक ​​कि पूर्णता के लिए सभी उपयोगकर्ताओं को प्रिंट करने के लिए एक फ़ंक्शन भी आवश्यक था।

/**
Creates an User Object and adds it to the users Collection.
*/
var addUser = (username, fullname, age, gender) => {
    let an_user = new User(username, fullname, age, gender);
    users.set(username, an_user);
}

/**
Returns an User Object associated with the given username in the Collection.
*/
var getUser = (username) => {
    return users.get(username);
}

/**
Deletes an User Object associated with the given username in the Collection.
*/
var deleteUser = (username) => {
    users.delete(username);
}

/**
Prints summary of all the User Objects in the Collection.
*/
var printUsers = () => {
    users.forEach((user) => {
        user.print();
    });
}

उपरोक्त सभी कोड के साथ, कहते हैं NodeJS , केवल usersमानचित्र में पूरी प्रक्रिया के भीतर उपयोगकर्ता ऑब्जेक्ट का संदर्भ है। व्यक्तिगत उपयोगकर्ता वस्तुओं का कोई अन्य संदर्भ नहीं है।

इस कोड को इंटरएक्टिव NodeJS शेल चला रहा है, उदाहरण के रूप में मैं चार उपयोगकर्ताओं को जोड़ता हूं और उन्हें प्रिंट करता हूं: उपयोगकर्ताओं को जोड़ना और प्रिंट करना

अतिरिक्त कोडिंग का उपयोग किए बिना उपयोगकर्ताओं के लिए अधिक जानकारी जोड़ें

अब कहते हैं कि एक नई सुविधा की आवश्यकता है जिसमें प्रत्येक उपयोगकर्ता सोशल मीडिया प्लेटफ़ॉर्म (एसएमपी) लिंक को उपयोगकर्ता वस्तुओं के साथ ट्रैक करने की आवश्यकता है।

यहां यह भी महत्वपूर्ण है कि यह सुविधा मौजूदा कोड में न्यूनतम हस्तक्षेप के साथ लागू की जानी चाहिए।

यह निम्नलिखित तरीके से WeakMaps के साथ संभव है।

मैं ट्विटर, फेसबुक, लिंक्डइन के लिए तीन अलग-अलग WeakMaps जोड़ता हूं।

/*
WeakMaps for Social Media Platforms (SMPs).
Could be replaced by a single Map which can grow
dynamically based on different SMP names . . . anyway...
*/
var sm_platform_twitter = new WeakMap();
var sm_platform_facebook = new WeakMap();
var sm_platform_linkedin = new WeakMap();

एक सहायक फ़ंक्शन, getSMPWeakMapकेवल दिए गए SMP नाम के साथ जुड़े WeakMap को वापस करने के लिए जोड़ा जाता है।

/**
Returns the WeakMap for the given SMP.
*/
var getSMPWeakMap = (sm_platform) => {
    if(sm_platform == "Twitter") {
        return sm_platform_twitter;
    }
    else if(sm_platform == "Facebook") {
        return sm_platform_facebook;
    }
    else if(sm_platform == "LinkedIn") {
        return sm_platform_linkedin;
    }
    return undefined;
}

दिए गए SMP WeakMap में एक उपयोगकर्ता SMP लिंक जोड़ने का कार्य।

/**
Adds a SMP link associated with a given User. The User must be already added to the Collection.
*/
var addUserSocialMediaLink = (username, sm_platform, sm_link) => {
    let user = getUser(username);
    let sm_platform_weakmap = getSMPWeakMap(sm_platform);
    if(user && sm_platform_weakmap) {
        sm_platform_weakmap.set(user, sm_link);
    }
}

एक फ़ंक्शन केवल उन उपयोगकर्ताओं को प्रिंट करने के लिए है जो दिए गए एसएमपी पर मौजूद हैं।

/**
Prints the User's fullname and corresponding SMP link of only those Users which are on the given SMP.
*/
var printSMPUsers = (sm_platform) => {
    let sm_platform_weakmap = getSMPWeakMap(sm_platform);
    console.log(`Users of ${sm_platform}:`)
    users.forEach((user)=>{
        if(sm_platform_weakmap.has(user)) {
            console.log(`\t${user.fullname} : ${sm_platform_weakmap.get(user)}`)
        }
    });
}

अब आप उपयोगकर्ताओं के लिए SMP लिंक जोड़ सकते हैं, साथ ही प्रत्येक उपयोगकर्ता के कई SMP पर लिंक होने की संभावना है।

... पहले के उदाहरण के साथ जारी रखते हुए, मैं उपयोगकर्ताओं के लिए एसएमपी लिंक जोड़ता हूं, उपयोगकर्ताओं के लिए कई लिंक बिल और सारा और फिर प्रत्येक एसएमपी के लिंक अलग-अलग प्रिंट करते हैं: उपयोगकर्ताओं को एसएमपी लिंक जोड़ना और उन्हें प्रदर्शित करना

अब कहते हैं कि उपयोगकर्ता को usersकॉल करके मानचित्र से हटा दिया गया हैdeleteUser । जो उपयोगकर्ता ऑब्जेक्ट के लिए एकमात्र संदर्भ निकालता है। यह बदले में SMP WeakMaps के किसी भी / सभी से SMP लिंक को हटा देगा (कचरा संग्रह द्वारा) उपयोगकर्ता ऑब्जेक्ट के बिना इसके SMP लिंक के किसी भी उपयोग करने का कोई तरीका नहीं है।

... उदाहरण के साथ जारी रखते हुए, मैं उपयोगकर्ता बिल को हटाता हूं और फिर उसके साथ जुड़े एसएमपी के लिंक का प्रिंट आउट लेता हूं:

उपयोगकर्ता बिल को मैप से हटाने के साथ ही एसएमपी लिंक को हटा देता है

व्यक्तिगत रूप से SMP लिंक को अलग से हटाने के लिए किसी भी अतिरिक्त कोड की आवश्यकता नहीं है और इस सुविधा से पहले मौजूदा कोड को वैसे भी संशोधित नहीं किया गया था।

यदि WeakMaps के साथ / बिना इस सुविधा को जोड़ने का कोई और तरीका है तो कृपया बेझिझक टिप्पणी कर सकते हैं।


_____nice______
Aleks
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.