ES6 मानचित्र और कमजोर मानचित्र में क्या अंतर है?


92

खोज रहे हैं इस और इस MDN पृष्ठों यह मैप्स और WeakMaps के बीच फर्क सिर्फ इतना है की तरह लगता है WeakMaps के लिए एक लापता "आकार" संपत्ति है। लेकिन क्या यह सच है? उनमें क्या अंतर है?


इसका असर जीसी पर पड़ा है। WeakMaps में उनकी चाबियां एकत्र की जा सकती हैं।
जॉन ड्वोरक

@JDDvorak एमडीएन पर इसके बारे में कोई उदाहरण नहीं दिया गया है। AWeakMap.get (कुंजी) की तरह; // कहते हैं, 2 ... (जीसी कार्रवाई) ... aWeakMap.get (कुंजी); // कहते हैं, अपरिभाषित
दमित्री सोरिन

1
आपका उदाहरण असंभव है। keyएकत्र नहीं किया जा सकता, क्योंकि यह आपके द्वारा संदर्भित है।
जॉन ड्वोरक

1
डिजाइन निर्णय यह है कि जावास्क्रिप्ट में जीसी क्रियाएं अदृश्य हैं। आप GC को उसकी बात करते हुए नहीं देख सकते।
जॉन ड्वोरक

1
इस समस्या के बारे में अधिक जानकारी के लिए संबंधित उत्तर देखें ।
बेंजामिन ग्रुएनबाम

जवाबों:


53

से बहुत ही पृष्ठ, अनुभाग " क्यों कमजोर मानचित्र? " :

अनुभवी जावास्क्रिप्ट प्रोग्रामर ध्यान देंगे कि यह एपीआई 4 एपीआई विधियों द्वारा साझा किए गए दो सरणियों (कुंजी के लिए एक, मूल्यों के लिए एक) के साथ जावास्क्रिप्ट में लागू किया जा सकता है। इस तरह के कार्यान्वयन में दो मुख्य असुविधाएँ होंगी। पहला एक O (n) खोज है (n मानचित्र में कुंजियों की संख्या होने के नाते)। दूसरा एक मेमोरी लीक मुद्दा है। मैन्युअल रूप से लिखित नक्शों के साथ, चाबियों का सरणी मुख्य वस्तुओं के संदर्भों को बनाए रखेगा, जिससे उन्हें एकत्र होने से रोका जा सके। मूल WeakMaps में, प्रमुख वस्तुओं के संदर्भ को "कमजोर रूप से" रखा जाता है , जिसका अर्थ है कि वे कचरा संग्रह को नहीं रोकते हैं यदि वस्तु का कोई अन्य संदर्भ नहीं होगा।

संदर्भ कमजोर होने के कारण, WeakMap कुंजियाँ गणना योग्य नहीं हैं (यानी आपको कुंजियों की सूची देने की कोई विधि नहीं है)। यदि वे थे, तो सूची गैर-नियतत्ववाद का परिचय देते हुए, कचरा संग्रहण की स्थिति पर निर्भर करेगी।

[और इसीलिए उनके पास भी कोई sizeसंपत्ति नहीं है ]

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

- जो होगा "सामान्य" Mapरों । एमडीएन में उल्लेख नहीं किया गया है, लेकिन सद्भाव प्रस्ताव में , उनके पास भी है items, keysऔर valuesजनरेटर के तरीके और Iteratorइंटरफ़ेस को लागू करते हैं ।


तो new Map().get(x)एक समान दिखने के समय के बारे में एक सादे वस्तु से एक संपत्ति पढ़ने के रूप में है?
अलेक्जेंडर मिल्स

1
@AlexanderMills मैं यह नहीं देखता कि इस सवाल का क्या करना है, लेकिन यहां कुछ आंकड़े हैं । सामान्य तौर पर, हाँ वे समान हैं , और आपको उपयुक्त का उपयोग करना चाहिए
बरगी

इसलिए मेरी समझ है कि मानचित्र उस सरणी के कारण अपनी कुंजी को बनाए रखने के लिए एक आंतरिक सरणी बनाए रखता है। कचरा संग्रहकर्ता संदर्भ का खंडन करने में सक्षम नहीं है। सप्ताह के अंत में, इसमें एक ऐसा सरणी नहीं होता है जहाँ कुंजियाँ बनी रहती हैं ताकि बिना किसी संदर्भ के कुंजी को एकत्रित किया जा सके।
मोहन राम

@MohanRam A में WeakMapअभी भी प्रविष्टियों की एक सरणी (या अन्य संग्रह) है, यह सिर्फ कचरा संग्रहकर्ता को बताता है कि वे कमजोर संदर्भ हैं
बरगी

फिर वीकएंड कीज़ के लिए पुनरावृति का समर्थन क्यों नहीं किया जाता है?
मोहन राम

92

वे दोनों अलग-अलग व्यवहार करते हैं जब उनकी चाबियाँ / मूल्यों द्वारा संदर्भित कोई वस्तु हटा दी जाती है। नीचे दिए गए उदाहरण कोड लेते हैं:

var map = new Map();
var weakmap = new WeakMap();

(function(){
    var a = {x: 12};
    var b = {y: 12};

    map.set(a, 1);
    weakmap.set(b, 2);
})()

उपरोक्त IIFE को निष्पादित किया जाता है कोई रास्ता नहीं है जिसे हम संदर्भित कर सकते हैं {x: 12}और {y: 12}अब। कचरा इकट्ठा करने वाला आगे बढ़ता है और "बीकैप" से कुंजी बी पॉइंटर को हटाता है {y: 12}और मेमोरी से भी निकालता है। लेकिन "मैप" के मामले में, कचरा संग्रहकर्ता "मैप" से एक पॉइंटर नहीं हटाता है {x: 12}और मेमोरी से भी नहीं हटाता है।

सारांश: WeakMap कचरा संग्रहकर्ता को अपना कार्य करने की अनुमति देता है लेकिन मानचित्र नहीं।

संदर्भ: http://qnimate.com/difference-between-map-and-weakmap-in-javascript/


12
इसे स्मृति से क्यों नहीं हटाया गया है? क्योंकि आप अभी भी इसे संदर्भित कर सकते हैं! map.entries().next().value // [{x:12}, 1]
बरगी

4
यह एक स्वयंभू समारोह नहीं है। यह एक फंक्स्ड फंक्शन एक्सप्रेशन है। benalman.com/news/2010/11/…
Olson.dev

फिर कमजोर और वस्तु के बीच क्या अंतर है
मुहम्मद उमेर

@MuhammadUmer: ऑब्जेक्ट में केवल स्ट्रिंग 'कुंजियाँ' हो WeakMapसकती हैं , जबकि केवल गैर-आदिम कुंजियाँ हो सकती हैं (कुंजियाँ या संख्याएँ या Symbolकुंजियाँ, केवल सरणियाँ, ऑब्जेक्ट्स, अन्य मानचित्र, आदि)।
अहमद फ़सीह

1
@nnnnnn हाँ कि अंतर है, तो वह अभी भी में यह Map में नहीं बल्किWeakMap
अलेक्जेंडर Derck

75

हो सकता है कि अगली व्याख्या किसी के लिए अधिक स्पष्ट हो।

var k1 = {a: 1};
var k2 = {b: 2};

var map = new Map();
var wm = new WeakMap();

map.set(k1, 'k1');
wm.set(k2, 'k2');

k1 = null;
map.forEach(function (val, key) {
    console.log(key, val); // k1 {a: 1}
});

k2 = null;
wm.get(k2); // undefined

जैसा कि आप देखते हैं, k1मेमोरी से की को हटाने के बाद भी हम इसे मैप के अंदर एक्सेस कर सकते हैं। उसी समय k2WeakMap की कुंजी को हटाने से इसे wmसंदर्भ से भी हटा दिया जाता है।

यही कारण है कि WeakMap forEach की तरह शानदार तरीके नहीं है, क्योंकि WeakMap कुंजियों की सूची जैसी कोई चीज नहीं है, वे सिर्फ अन्य वस्तुओं के संदर्भ हैं।


10
अंतिम पंक्ति में, निश्चित रूप से, wm.get (null) अपरिभाषित होगा।
21

8
मोज़िला साइट, कुडोस से कॉपी और पेस्ट करने से बेहतर जवाब।
जोएल हर्नांडेज 13

2
में forEach, (key, val)वास्तव में होना चाहिए(val, key)
मिगुएल मोटा

अविश्वसनीय कैसे एक उदाहरण है कि कोई मतलब नहीं है इतने सारे upvotes मिल
अल्फ्रेडोपासिनो

34

एक और अंतर (स्रोत: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap ):

WeakMaps की कुंजियाँ केवल ऑब्जेक्ट प्रकार की होती हैं। कुंजी के रूप में आदिम डेटा प्रकार की अनुमति नहीं है (जैसे एक प्रतीक एक कमजोर मानचित्र कुंजी नहीं हो सकता है)।

न ही एक स्ट्रिंग, संख्या, या बूलियन को एक WeakMapकुंजी के रूप में इस्तेमाल किया जा सकता है । A कुंजी के लिए आदिम मानों का उपयोग Map कर सकता है

w = new WeakMap;
w.set('a', 'b'); // Uncaught TypeError: Invalid value used as weak map key

m = new Map
m.set('a', 'b'); // Works

6
मामले में किसी ने आश्चर्य किया: मैं इसके पीछे के कारण की कल्पना कर सकता हूं: आप आदिम प्रकार के संदर्भों को रख या पास नहीं कर सकते। इसलिए एक WeakMap में कुंजी इसका एकमात्र संदर्भ होगा, कभी भी। इस तरह से कचरा संग्रहण संभव नहीं होगा। मुझे नहीं पता कि क्या कमजोर संदर्भ असंभव हैं या बस समझ में नहीं आता है। लेकिन या तो कुंजी को कुछ ऐसा होना चाहिए जो कमजोर रूप से संदर्भित हो सके।
एंड्रियास लिनर्ट

3

से Javascript.info

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

let john = { name: "John" };
let array = [ john ];
john = null; // overwrite the reference

// john is stored inside the array, so it won't be garbage-collected
// we can get it as array[0]

उसी के समान, यदि हम किसी वस्तु का उपयोग नियमित मानचित्र में कुंजी के रूप में करते हैं, तो जबकि मानचित्र मौजूद है, वह वस्तु भी मौजूद है। यह स्मृति को घेरता है और कचरा एकत्र नहीं हो सकता है

let john = { name: "John" };
let map = new Map();
map.set(john, "...");
john = null; // overwrite the reference

// john is stored inside the map,
// we can get it by using map.keys()

WeakMap - अब, यदि हम इसमें एक कुंजी के रूप में किसी वस्तु का उपयोग करते हैं, और उस वस्तु के लिए कोई अन्य संदर्भ नहीं हैं - यह स्वचालित रूप से मेमोरी (और नक्शे से) से हटा दिया जाएगा।

let john = { name: "John" };
let weakMap = new WeakMap();
weakMap.set(john, "...");
john = null; // overwrite the reference

// john is removed from memory!

3

जावास्क्रिप्ट में हथियार किसी भी कुंजी या मूल्यों को नहीं रखता है, यह सिर्फ एक अद्वितीय आईडी का उपयोग करके मुख्य मूल्य में हेरफेर करता है करता है और एक संपत्ति को मुख्य वस्तु में परिभाषित करता है।

क्योंकि यह संपत्ति को key objectविधि से परिभाषित करता है Object.definePropert(), कुंजी को आदिम प्रकार नहीं होना चाहिए

और इसलिए भी कि WeapMap में वास्तव में महत्वपूर्ण मूल्य जोड़े नहीं होते हैं, हमें कमजोर संपत्ति की लंबाई संपत्ति नहीं मिल सकती है।

और हेरफेर किए गए मान को मुख्य ऑब्जेक्ट को वापस सौंपा गया है, कचरा संग्रहकर्ता आसानी से कुंजी का उपयोग कर सकता है यदि यह बिना उपयोग में है।

कार्यान्वयन के लिए नमूना कोड।

if(typeof WeapMap != undefined){
return;
} 
(function(){
   var WeapMap = function(){
      this.__id = '__weakmap__';
   }
        
   weakmap.set = function(key,value){
       var pVal = key[this.__id];
        if(pVal && pVal[0] == key){
           pVal[1]=value;
       }else{
          Object.defineProperty(key, this.__id, {value:[key,value]});
          return this;
        }
   }

window.WeakMap = WeakMap;
})();

कार्यान्वयन का संदर्भ


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

@AndreasRossberg इस कार्यान्वयन में मैंने हार्डकोड को जोड़ा है id, लेकिन यह कुछ Math.random और Date.now (), आदि का उपयोग करके अद्वितीय होना चाहिए और इस डायनेमिक आईडी को जोड़कर, पहले बिंदु को हल किया जा सकता है। क्या आप मुझे अंतिम दो बिंदुओं के लिए कोई समाधान प्रदान कर सकते हैं।
रवि सेवा १५

प्रतीकों का उपयोग करके पहली समस्या को अधिक सुरुचिपूर्ण ढंग से हल किया जाता है। बाद के दो को जेएस के भीतर हल नहीं किया जा सकता है, यही कारण है कि वीकेप को भाषा में एक आदिम होना चाहिए।
एंड्रियास रॉसबर्ग

1

WeakMap कुंजियाँ वस्तुएं होनी चाहिए, न कि आदिम मूल्य।

let weakMap = new WeakMap();

let obj = {};

weakMap.set(obj, "ok"); // works fine (object key)

// can't use a string as the key
weakMap.set("test", "Not ok"); // Error, because "test" is not an object

क्यों????

आइए नीचे उदाहरण देखें।

let user = { name: "User" };

let map = new Map();
map.set(user, "...");

user = null; // overwrite the reference

// 'user' is stored inside the map,
// We can get it by using map.keys()

यदि हम किसी वस्तु को नियमित रूप से कुंजी के रूप में उपयोग Mapकरते हैं, तो जबकि Map मौजूद भी वह वस्तु मौजूद रहती है। यह स्मृति को घेरता है और कचरा एकत्र नहीं हो सकता है।

WeakMapइस पहलू में मौलिक रूप से भिन्न है। यह प्रमुख वस्तुओं के कचरा-संग्रह को नहीं रोकता है।

let user = { name: "User" };

let weakMap = new WeakMap();
weakMap.set(user, "...");

user = null; // overwrite the reference

// 'user' is removed from memory!

यदि हम इसमें किसी वस्तु का उपयोग कुंजी के रूप में करते हैं, और उस वस्तु के लिए कोई अन्य सन्दर्भ नहीं हैं - तो यह स्वतः ही (और मानचित्र से) मेमोरी से हटा दी जाएगी।

WeakMap पुनरावृत्ति और विधियों कीज़ () , मानों () , प्रविष्टियों () का समर्थन नहीं करता है , इसलिए इससे सभी कुंजी या मान प्राप्त करने का कोई तरीका नहीं है।

WeakMap में केवल निम्न विधियाँ हैं:

  • weakMap.get (key)
  • weakMap.set (कुंजी, मूल्य)
  • weakMap.delete (key)
  • weakMap.has (key)

यह स्पष्ट है कि यदि किसी वस्तु ने अन्य सभी संदर्भों को खो दिया है (जैसे ऊपर दिए गए कोड में 'उपयोगकर्ता'), तो यह स्वचालित रूप से कचरा एकत्र करना है। लेकिन तकनीकी तौर पर यह बिल्कुल निर्दिष्ट नहीं है जब सफाई होती है।

जावास्क्रिप्ट इंजन तय करता है कि। यह स्मृति सफाई तुरंत करने या प्रतीक्षा करने और बाद में सफाई करने का चयन कर सकता है जब अधिक विलोपन होता है। इसलिए, तकनीकी रूप से वर्तमान तत्व की गणना WeakMapज्ञात नहीं है। इंजन ने इसे आंशिक रूप से साफ किया है या नहीं किया है। उस कारण से, सभी कुंजियों / मानों तक पहुंचने वाले तरीकों का समर्थन नहीं किया जाता है।

नोट: - WeakMap के लिए आवेदन का मुख्य क्षेत्र एक अतिरिक्त डेटा स्टोरेज है। जैसे किसी वस्तु को कैशिंग तब तक करना जब तक वह वस्तु कचरा एकत्रित न हो जाए।

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