2012-01-29 14 views
7

संदर्भ: http://ejohn.org/blog/simple-class-instantiation/जॉन Resig के साधारण क्लास इन्स्टेन्शियशन और "सख्त का उपयोग करें"

// makeClass - By John Resig (MIT Licensed) 
function makeClass(){ 
    return function(args){ 
    if (this instanceof arguments.callee) { 
     if (typeof this.init == "function") 
     this.init.apply(this, args.callee ? args : arguments); 
    } else 
     return new arguments.callee(arguments); 
    }; 
} 

मैं सोच रहा था, यदि एक ही कार्यक्षमता लागू करने के लिए किसी भी ECMAScript 5 शिकायत कर सकते हैं। समस्या यह है कि arguments.callee तक पहुंच सख्त मोड में बहिष्कृत है।

उत्तर

4

मैं समझता हूँ के रूप में यह arguments.callee है सख्त मोड, ऐसी स्थिति में आप इसे उपयोग करने के लिए जारी कर सकते हैं में नहीं पदावनत; बल्कि, यह हटा दिया गया है और उपयोग का प्रयास किया जाएगा (या माना जाता है) अपवाद फेंक देगा।

वर्कअराउंड नामित अज्ञात कार्यों का उपयोग करना है, यदि आप ऑक्सीमोरोन को माफ कर देंगे। वास्तव में मुझे "named function expressions" कहना चाहिए। एक उदाहरण:

function someFunc(){ 
    return function funcExpressionName(args){ 
    if (this instanceof funcExpressionName) { 
     // do something 
    } else 
     return new funcExpressionName(arguments); 
    }; 
} 

नाम उपलब्ध कराने, मेरे उदाहरण में funcExpressionName कहीं भी समारोह में यह लागू होता है अंदर छोड़कर से सुलभ होना चाहिए नहीं है, लेकिन दुर्भाग्य से आईई अन्य विचारों है (जैसा कि आप देख सकते हैं यदि आप Google it) ।

उदाहरण अपने प्रश्न में मैं args.callee को संभालने के लिए कैसे के बाद से मैं कैसे है कि फोन करने के समारोह के द्वारा निर्धारित है पता नहीं है, लेकिन arguments.callee के उपयोग मेरी उदाहरण के अनुसार प्रतिस्थापित किया जाएगा यकीन नहीं है के लिए।

1

जॉन रेसिग का मूल कोड पैरामीटर रहित कन्स्ट्रक्टर के साथ विफल रहता है।

var Timestamp = makeClass(); 
Timestamp.prototype.init = function() { 
    this.value = new Date(); 
}; 

// ok 
var timestamp = Timestamp(); 
alert(timestamp.value); 

// TypeError: args is undefined 
var timestamp = new Timestamp(); 
alert(timestamp.value); 

लेकिन यह निम्न पंक्ति

this.init.apply(this, args && args.callee ? args : arguments); 
2

ऊपर विचार nnnnnn द्वारा दिए गए का उपयोग कर ठीक किया जा सकता काफी अच्छा है। और आईई मुद्दों से बचने के लिए मैं निम्नलिखित समाधान का सुझाव देता हूं।

function makeClassStrict() { 
    var isInternal, instance; 

    var constructor = function(args) { 
     // Find out whether constructor was called with 'new' operator. 
     if (this instanceof constructor) { 
      // When an 'init' method exists, apply it to the context object. 
      if (typeof this.init == "function") { 
       // Ask private flag whether we did the calling ourselves. 
       this.init.apply(this, isInternal ? args : arguments); 
      } 
     } else { 
      // We have an ordinary function call. 

      // Set private flag to signal internal instance creation. 
      isInternal = true;           
      instance = new constructor(arguments); 
      isInternal = false;           
      return instance; 
     } 
    }; 

    return constructor; 
} 

नोट कैसे हम एक आंतरिक ध्वज का उपयोग करके // do something भाग में args.callee के संदर्भ से बचें।