2011-08-30 7 views
9

मैं कुछ एक्शनस्क्रिप्ट 3 कोड लिख रहा हूं जो रनटाइम पर निर्धारित ऑब्जेक्ट को विधि लागू करने का प्रयास करता है। Function.apply और Function.call दोनों के लिए AS3 दस्तावेज़ दोनों इंगित करते हैं कि उन कार्यों के लिए पहला तर्क वह ऑब्जेक्ट है जिसे फ़ंक्शन निष्पादित होने पर 'इस' मान के रूप में उपयोग किया जाएगा।फ़ंक्शन। इस एआरजी पैरामीटर का उपयोग न करें

हालांकि, मैंने पाया है कि सभी मामलों में जब कार्य निष्पादित किया जा रहा है, तो एक विधि है, लागू/कॉल करने के लिए पहला पैरामीटर उपयोग नहीं किया जाता है, और 'यह' हमेशा उस मूल वस्तु को संदर्भित करता है जिस पर वह विधि बंधी गई थी।

package 
{ 
    import flash.display.Sprite;  
    public class FunctionApplyTest extends Sprite 
    { 
     public function FunctionApplyTest() 
     { 
      var objA:MyObj = new MyObj("A"); 
      var objB:MyObj = new MyObj("B"); 

      objA.sayName(); 
      objB.sayName(); 

      objA.sayName.apply(objB, []); 
      objA.sayName.call(objB); 
     } 
    } 
} 

internal class MyObj 
{ 
    private var _name:String; 
    public function MyObj(name:String) 
    { 
     _name = name; 
    } 
    public function sayName():void 
    { 
     trace(_name); 
    } 
} 

आउटपुट::

A 
B 
A 
A 

ऊपर कोड के लिए एक मामूली संशोधन के एक इन-लाइन गुमनाम समारोह जो को संदर्भित करता है बनाने के लिए 'इस' से पता चलता है कि सही यहाँ कुछ उदाहरण कोड और इसके उत्पादन है व्यवहार तब होता है जब फ़ंक्शन लागू/कॉल किया जाता है वह बाध्य विधि नहीं है।

क्या मैं किसी विधि पर इसका उपयोग करने का प्रयास करते समय लागू/कॉल गलत उपयोग कर रहा हूं? AS3 प्रलेखन विशेष रूप से इस मामले के लिए कोड प्रदान करता है, तथापि:

myObject.myMethod.call(myOtherObject, 1, 2, 3); 

अगर यह वास्तव में टूट गया है, वहाँ किसी भी काम के आसपास कार्यों में लक्ष्य तरीकों (जो काफी बदसूरत होगा मेरी राय में) करने के अतिरिक्त है?

+0

मुझे यह कहना होगा कि अगर आपको इस तरह के कोडिंग की आवश्यकता है तो आप कुछ गलत कर रहे हैं। ऐसा करने से आप वास्तव में क्या करने की कोशिश कर रहे हैं? –

+0

इसे मेरे अंत में परीक्षण किया। एक बग की तरह लगता है। जिरा में खोज करने का प्रयास करें: http://bugs.adobe.com/jira/browse और यदि आपको यह नहीं मिला है, तो इसे – divillysausages

+0

सबमिट करें, यह भाषा बग नहीं है, लेकिन खराब लिखित दस्तावेज –

उत्तर

17

इसकी नहीं एक "बग", लेकिन call और apply के लिए दस्तावेज़ बहुत भ्रामक है और समझाने का सब पर एक अच्छा काम नहीं करता है क्या चल रहा है। तो यहां क्या हो रहा है इसकी एक व्याख्या है।

Methods एक्शनस्क्रिप्ट में Functions से अलग हैं। Methods को कक्षा परिभाषा के हिस्से के रूप में परिभाषित किया गया है, और विधियां हमेशा उस उदाहरण से बंधी जाती हैं। this link के दूसरे तरीके देखें। वहां से उद्धरण:

तरीके ऐसे कार्य हैं जो कक्षा परिभाषा का हिस्सा हैं। एक बार वर्ग का उदाहरण बनने के बाद, उस विधि के लिए एक विधि बाध्य है। किसी वर्ग के बाहर घोषित एक फ़ंक्शन के विपरीत, जिस विधि से जुड़ा हुआ है, उसके अलावा एक विधि का उपयोग नहीं किया जा सकता है।

तो जब आप MyObj का उदाहरण बनाते हैं, तो इसके सभी तरीके उस उदाहरण से बंधे होते हैं। यही कारण है कि जब आप call या apply का उपयोग करने का प्रयास करते हैं, तो आप this ओवरराइड नहीं देख रहे हैं। विवरण के लिए Bound Methods पर अनुभाग देखें।

देखें, this documentलक्षण के लिए स्पष्टीकरण आपत्ति, जो actionscript इसके लिए जिम्मेदार शायद है तरीकों को हल करने और पर्दे के पीछे प्रदर्शन के कारणों के लिए प्रयोग किया जाता करने के लिए उपयोग करता है।

var TestClass = function(data) { 
    var self = this; 
    this.data = data; 
    this.boundWork = function() { 
     return self.constructor.prototype.unboundWork.apply(self, arguments); 
    }; 
}; 

TestClass.prototype.unboundWork = function() { 
    return this.data; 
}; 

तब:

var a = new TestClass("a"); 
var b = new TestClass("b"); 

alert(a.boundWork()); // a 
alert(b.boundWork()); // b 

alert(a.unboundWork()); // a 
alert(b.unboundWork()); // b 

alert(a.boundWork.call(b)); // a 
alert(a.boundWork.call(undefined)); // a 

alert(a.unboundWork.call(b)); // b 

या और भी दिलचस्प:

var method = a.unboundWork; 
method() // undefined. ACK! 

बनाम:

method = a.boundWork; 
method() // a. TADA MAGIC! 
कि या वर्ग तरीकों का पालन ECMAScript पैटर्न के लिए बस वाक्यात्मक चीनी हैं

नोटिस कि boundWork हमेशा के लिए call या apply के साथ जो भी हो, उस मामले के संदर्भ में निष्पादित किया जाएगा। जो, एक्शनस्क्रिप्ट में, यह व्यवहार बिल्कुल सही है कि क्लास विधियां उनके उदाहरण से बंधी क्यों हैं। इसलिए कोई फर्क नहीं पड़ता कि उनका उपयोग कहां किया जाता है, फिर भी वे उस उदाहरण को इंगित करते हैं जो वे आए थे (जो क्रियालेख घटना घटना को थोड़ा और अधिक "सचे" बनाता है)। एक बार जब आप इसे समझ लेंगे, तो एक कार्य-आसपास स्पष्ट होना चाहिए।

उन स्थानों के लिए जहां आप कुछ जादू करना चाहते हैं, प्रोटोटाइप कार्यों के पक्ष में एक्शनस्क्रिप्ट 3 आधारित हार्ड-बाध्य विधियों से बचें।

package 
{ 
    import flash.display.Sprite;  
    public class FunctionApplyTest extends Sprite 
    { 
     public function FunctionApplyTest() 
     { 
      var objA:MyObj = new MyObj("A"); 
      var objB:MyObj = new MyObj("B"); 

      objA.sayName(); 
      objB.sayName(); 

      objA.sayName.apply(objB, []); // a 
      objA.sayName.call(objB); // a 

      objA.pSayName.call(objB) // b <--- 
     } 
    } 
} 

internal dynamic class MyObj 
{ 
    private var _name:String; 
    public function MyObj(name:String) 
    { 
     _name = name; 
    } 
    public function sayName():void 
    { 
     trace(_name); 
    } 

    prototype.pSayName = function():void { 
     trace(this._name); 
    }; 
} 

सूचना sayName और pSayName के बीच घोषणा अंतर:

उदाहरण के लिए, निम्नलिखित ActionScript कोड पर विचार करें। sayName हमेशा उस उदाहरण के लिए बाध्य होगा जो इसे बनाया गया था। pSayName एक ऐसा फ़ंक्शन है जो MyObj के उदाहरणों के लिए उपलब्ध है लेकिन इसके किसी विशेष उदाहरण से बाध्य नहीं है।

call और apply के लिए दस्तावेज़ जब तक आप प्रोटोटाइप functions है और वर्ग methods, जो मैं यह बिल्कुल उल्लेख नहीं लगता कि के बारे में बात कर रहे हैं तकनीकी रूप से सही कर रहे हैं।

+0

इसे समझाने के लिए बहुत बहुत धन्यवाद, यह बहुत प्रबुद्ध था! मुझे लगता है कि शायद यह मामला नहीं है कि विधि घोषणा आपके पहले कोड उदाहरण के लिए वाक्य रचनात्मक चीनी है, क्योंकि यदि यह सत्य था तो क्लासटाइप.प्रोटोटाइप में प्रत्येक अनबाउंड विधियों के लिए गुण होंगे। मेरे लिए ऐसा लगता है कि यह दोनों दुनिया में सबसे अच्छा होगा, कुछ हद तक पायथन के तंत्र के समान होगा जहां objA.sayName() MyObj.sayName (objA) के लिए वाक्य रचनात्मक चीनी है। –

1

वाह, यह बहुत आश्चर्य की बात है ऊ

रूप में अच्छी तरह मेरी तरफ परीक्षण किया गया और मानकों में पारित करने के लिए के रूप में अच्छी कोशिश की और सभी मामलों में, पारित कर दिया thisArg सब पर इस्तेमाल किया जा प्रतीत नहीं होता है (स्पष्ट रूप से की तरह लगता है मेरे लिए एक बग)।

मुझे कुछ समान उपयोग करना पड़ा, लेकिन ऑब्जेक्ट का उदाहरण बनाये बिना विधि तक पहुंचने की आवश्यकता की अतिरिक्त बाधा थी (जो अन्य भाषाओं में संभव है लेकिन AS3> < में नहीं है)। इसलिए मैंने स्थैतिक कार्यों को समाप्त कर दिया और इसके बजाय अपना "thisArg" पास कर दिया।

static public function SayName(thisArg : MyObj) : void 
{ 
    trace(thisArg._name); 
} 

नहीं सबसे बड़ी के बाद से आप शायद इस तरह कोड को दोगुना करने पहुंच जाएंगे>:

तो स्थिर कार्यों बनाने के बजाय एक संभव समाधान नहीं है। <

वैकल्पिक रूप से, अगर तरीकों सार्वजनिक कर रहे हैं, तो आप समारोह के नाम के बजाय समारोह के बचाने के लिए और की तरह कुछ कर रही द्वारा यह विधि है पहुँच सकते हैं:

var funcName : String = "sayName"; 
objB[funcName].apply(null, []); 
objB[funcName].call(null); 

हालांकि, इस के दायरे के आधार पर सीमित है आपके विधि (सार्वजनिक विधियों को हर जगह से इस तरह इस्तेमाल किया जा सकता है, उसी वर्ग के भीतर आंतरिक विधियां जैसे आपकी कक्षा और निजी विधियों को केवल कक्षा के अंदर से)। इसलिए यह आपकी विधि के वास्तविक फ़ंक्शन इंस्टेंस का उपयोग करने से कहीं अधिक सीमित है जिसका उपयोग कहीं से भी किया जा सकता है।

यह एक बहुत ही बुरा बग की तरह लगता है ओ। मुझे आशा है कि किसी और के पास इसका बेहतर समाधान होगा।

1

क्या आपने वास्तव में this संदर्भ का स्पष्ट रूप से उपयोग करने की कोशिश की है, यानी।:

internal class MyObj 
{ 
    private var _name:String; 
    public function MyObj(name:String) 
    { 
     _name = name; 
    } 
    public function sayName():void 
    { 
     trace(this._name); 
    } 
} 

यह हो सकता है कि जब this कीवर्ड छोड़ दिया जाता है, मूल उदाहरण क्षेत्र/चर को देखने के लिए, जबकि क्या thisArg वास्तव में करता है फिर से बाध्य करने के लिए this कीवर्ड है प्रयोग किया जाता है। यदि ऐसा है तो यह सबसे अच्छा आर्केन है, लेकिन यह एक कोशिश के लायक हो सकता है।

+0

+1 'thisArg' पुनः- 'इस' बांधो। मुझे कुछ [समान उदाहरण] (http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/Array.html#filter%28%29) प्रदान करने के लिए 'ऐरे' दस्तावेज़ मिल गए हैं व्यवहार। – NoobsArePeople2

+0

हां, मैंने स्पष्ट रूप से 'इस' कीवर्ड का उपयोग करने की कोशिश की, और दुर्भाग्य से वही व्यवहार मिला। उपरोक्त लिंक किए गए Array.filter के लिए प्रलेखन स्पष्ट रूप से कहता है कि कॉलबैक फ़ंक्शन एक विधि है, तो 'thisArg' पैरामीटर शून्य होना चाहिए, इसलिए ऐसा लगता है कि फ़िल्टर के कार्यान्वयनकर्ता भी इस समस्या में भाग गए। –

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