2015-03-06 7 views
8

काम करता है मैंने सोचा था कि QML समर्थित गुमनाम कार्यों का जावास्क्रिप्ट का समर्थन और तथ्य यह है कि कार्यों प्रथम श्रेणी वस्तुओं रहे हैं की वजह से लैम्ब्डा काम करता है, लेकिन वे काम नहीं करते मैं कैसे उम्मीद। इस कोड को लें:QML: लैम्ब्डा समारोह अप्रत्याशित रूप से

Item { 
    property var items: [] 

    function handler(item) { 
     console.log(item); 
    } 

    Component.onCompleted: { 
     for (var i = 0; i < 3; ++i) { 
      var item = someObj.createObject(); 
      item.someValueChanged.connect(function() { 
       handler(item); }); 

      items.push(item); 
      console.log("Adding:", item); 
     } 
    } 

    Component { 
     id: someObj 

     Item { 
      property bool someValue: false 

      Timer { 
       running: true 
       onTriggered: { 
        parent.someValue = true; 
       } 
      } 
     } 
    } 
} 

मैं लैम्ब्डा function() { handler(item); } उपयोग करने के लिए इतना है कि जब someObj::someValueChanged संकेत उत्सर्जित होता है उत्सर्जन आइटम handler(item) कार्य करने के लिए पारित हो जाता है कोशिश कर रहा हूँ।

मैं कि प्रत्येक पाश लैम्ब्डा का एक नया उदाहरण बन जाएगा और उस item संदर्भ कि पाश में बनाया someObj उदाहरण के संदर्भ ले मान लिया (अर्थात item लैम्ब्डा द्वारा कब्जा कर लिया जाएगा)। लेकिन उस मामले में हो प्रतीत नहीं होता है के रूप में उत्पादन होता है:

qml: Adding: QQuickItem_QML_1(0x2442aa0) 
qml: Adding: QQuickItem_QML_1(0x2443c00) 
qml: Adding: QQuickItem_QML_1(0x2445370) 
qml: QQuickItem_QML_1(0x2445370) 
qml: QQuickItem_QML_1(0x2445370) 
qml: QQuickItem_QML_1(0x2445370) 

आप देख सकते हैं, या तो पूरा समारोह प्रत्येक पाश या सिर्फ item संदर्भ पर बदला जा रहा है, ताकि अंत में केवल पिछले बनाया someObj को संदर्भित किया गया है। क्या कोई मुझे बता सकता है कि क्यों lambdas (अगर यह भी है) क्या मैं जिस तरह से उम्मीद करता हूं काम नहीं करता? और क्या यह एक क्यूएमएल मुद्दा है, या एक सामान्य जावास्क्रिप्ट एक है?

उत्तर

11

इस तरह की कोशिश कुछ:

item.someValueChanged.connect(function(temp) { 
    return function() { 
     handler(temp)} 
}(item)) 

सहज, है ना? : डी

यदि जेएस "ब्लॉक स्कोप" का उपयोग करता है तो प्रत्येक लूप पुनरावृत्ति के लिए 3 अलग-अलग item संदर्भित किया जाएगा, और यह "अपेक्षा के अनुसार काम करेगा"। लेकिन "फ़ंक्शन स्कोप" के साथ केवल एक item संदर्भित है, और यह इसके अंतिम मान का संदर्भ देता है, इस प्रकार उस हैक का उपयोग समय में प्रत्येक मान को "कैप्चर" करने की आवश्यकता है।

+0

आह, यह समझ में आता है (जेएस के लिए वैसे भी)। धन्यवाद! – cmannett85

+0

@ cmannett85 - यदि आप लैम्ब्डा में देरी चलाने की कोशिश करते हैं, तो सी ++ में क्या होगा, जो उस कार्य के स्थानीय लोगों को संदर्भित करता है जो दायरे से बाहर हो गए हैं? सबसे अच्छा मामला अगर यह शुरू करने के लिए ढेर पर था और स्टैक बाद में उस गहराई तक नहीं गया है और उस स्मृति को अधिलेखित नहीं किया गया है, तो यह काम कर सकता है, लेकिन अधिकतर यह क्रैश हो जाएगा। – dtech

+0

सिवाय इसके कि सी ++ में आप निर्दिष्ट कर सकते हैं कि क्या कब्जा कर लिया गया है _ और how_। कुछ ऐसा जो जेएस समर्थन नहीं करता है (कम से कम संस्करण जो QtQuick उपयोग करता है)। – cmannett85

संबंधित मुद्दे