2010-12-03 16 views
26

मैं यह जांचने में सक्षम होना चाहता हूं कि कोई दिया गया फ़ंक्शन खाली है या नहीं।यह निर्धारित करने के लिए कि कोई फ़ंक्शन खाली है या नहीं

function foo() {} 
function iAmEmpty(a) { 
    // yep, empty 
} 

कुछ, मुझे मिल गया है जो मैं, ठीक हो सकता है toString() और कुछ regexes का उपयोग करके लगता है कि कुछ प्रारंभिक खेल के चारों ओर के साथ: यह है, वहाँ जैसे उसके शरीर में कुछ भी नहीं है।

function foo(a, b, c) {} 

/^function[^{]+\{\s*\}/m.test(foo.toString()); // true 

function bar(a, b, c) { var d; } 

/^function[^{]+\{\s*\}/m.test(bar.toString()); // false 

मैं बस सोच रहा था कि कोई बेहतर दृष्टिकोण था या नहीं? क्या आप उपरोक्त के साथ कोई समस्या देख सकते हैं?

+0

अच्छा सवाल ... –

+1

जे एस प्रतिबिंब की अवधारणा मुझे lol बना है, लेकिन समस्या के रूप में; आपने व्हाइटस्पेस और मल्टीलाइन के साथ निपटाया है, इसलिए यह उतना ही अच्छा है जितना यह मिलता है। – annakata

+1

सभी निकायों की विधि निकायों को देखना न भूलें (यदि यह आपकी कल्पना है) – Brad

उत्तर

15

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

Kangax इस बारे में संक्षेप में लिखा है: http://perfectionkills.com/those-tricky-functions/

+0

लिंक के लिए धन्यवाद! मुझे नहीं पता था कि ब्राउज़र कार्यान्वयन में मतभेद इतने चरम थे। – nickf

+0

@Tim ES5: [Function.prototype।टूस्ट्रिंग] (http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.4.2) ES6 [Function.prototype.toString] (https://www.ecma-international.org /ecma-262/6.0/#sec-function.prototype.tostring) –

+0

@ मंसजयंथ: मुख्य शब्द "ठीक" है। दोनों चश्मे कहते हैं कि फ़ंक्शन का "कार्यान्वयन-निर्भर प्रतिनिधित्व" वापस कर दिया जाता है। –

2

मैं इस के लिए उपयोग नहीं दिख रहा है, लेकिन आप स्ट्रिंग के अंत के पैटर्न प्रस्तोता द्वारा यह सरल बना सकता है।

/[^{\s]\s*\}$/.test(String(bar)) 
5

सबसे अच्छी बात आप, कोशिश अधिकतम संभावनाओं फिट करने के लिए (के रूप में इस लक्ष्य को हासिल करने के लिए बहुत कठिन है) कर सकते हैं, पुस्तकालयों (बहुत तीर कार्यों के साथ काम करता है ) acorn या esprima जोड़ने के लिए है और जावास्क्रिप्ट समारोह की प्रक्रिया । यह आपके लिए पार्स करने के लिए इसे टोकननाइज़ करेगा, ताकि आप इसे अपनी पसंद के अनुसार संसाधित कर सकें, जांच कर सकते हैं कि वास्तव में शून्य कोड है या नहीं, या केवल गणना के बिना केवल परिवर्तनीय घोषणाएं हैं या न ही वापसी, आदि ...

लागू करने के लिए बहुत सरल है :

function check(f) { 
 
    console.log(""); 
 
    console.log("Checking", f); 
 
    var syntax = esprima.parse(f); 
 
    if (syntax.body.length != 1) { 
 
    console.log("Weird process"); 
 
    } else { 
 
    function processBody(body) { 
 
     if (!body || body.length == 0) { 
 
     console.log("Body seems empty. YAY!"); 
 
     } else { 
 
     for (var i = 0, command; command = body[i]; i++) { 
 
      if (command.type != "VariableDeclaration") { 
 
      console.log("Body has a", command.type, ", so is not empty."); 
 
      return; 
 
      } 
 
     } 
 
     console.log("Body has only variable declarations, so is empty! (or not, whatever fit your needs)"); 
 
     } 
 
    } 
 
    function process(dec) { 
 
     if (dec.type != "FunctionDeclaration") { 
 
     console.log("Weird declaration"); 
 
     } else { 
 
     console.log("Function", dec.id.name, "has", dec.params.length, "params"); 
 
     processBody(dec.body.body); 
 
     } 
 
    } 
 
    process(syntax.body[0]); 
 
    } 
 
} 
 

 
check("function hasReturn(arg1, arg2) {var a = arg1 + arg2;return a;}"); 
 
check("function hasArgumentsButNoBody(arg1, arg2) {}"); 
 
check("function isCompletelyEmptyWithSpacesAndTabsAndLinefeeds() { \t \t \r\n \r\n }"); 
 
check("function hasOnlyVariables() {var a, b = 2; var c = 1 + b;}");
<script src="https://cdnjs.cloudflare.com/ajax/libs/esprima/2.7.3/esprima.min.js"></script>

यह कार्यों नहीं चलेंगे, बस उन्हें पार्स, इसलिए गैर-सुरक्षित कार्यों के साथ चलाने के लिए सुरक्षित है।

7

तीर कार्यों ...

के रूप में मुझे यकीन है कि आप जानते हैं हूँ, javascriptarrow functions जो वास्तव में संक्षिप्त कर रहे हैं लेकिन दुर्भाग्य से अपने स्वच्छ regex साथ काम नहीं करते समर्थन करता है।

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

function eF() {} 

जो के रूप में हम isEmpty(eF) रिटर्न true साथ उम्मीद करेंगे:

isEmpty = f => /^function[^{]+\{\s*\}/m.test(f.toString()) 

अब, हम आसानी से एक खाली समारोह परीक्षण कर सकते हैं ।एक वास्तविक कार्य के साथ

और एक बार और अधिक:

function retOne() {return 1;} 

जो फिर से के रूप में isEmpty(retOne) रिटर्न false साथ की उम्मीद है। तो फिर एक खाली एक प्रारंभ करने में

हालांकि, इस मुद्दे को मैं का सामना करना पड़ा तीर कार्यों के साथ था, हम मूल की एक छोटी वाक्य रचना है:

eF =() => {} 

और उस के 'stringified' संस्करण एक के लिए काफी अलग है पहले:

"() => {}" 

में तो बेशक इस मामले कॉल isEmpty(eF) रिटर्न false जब हम true चाहते हैं। मुझे यकीन है कि आप अगर सभी कार्यों (यानी arrow functions सहित) खाली हैं परीक्षण करने के लिए आवश्यकता होती है, तो नहीं कर रहा हूँ, लेकिन यदि आप करते हैं, अपने regex को संशोधित करने की आवश्यकता होगी ...

मैं महान नहीं कर रहा हूँ उन्हें अपने आप को लिखित रूप में, लेकिन एक प्रयास किया है

(param1, param2, …, paramN) => { statements } 
(param1, param2, …, paramN) => expression 
// equivalent to: (param1, param2, …, paramN) => { return expression; } 

// Parentheses are optional when there's only one parameter name: 
(singleParam) => { statements } 
singleParam => { statements } 

जो दिखाता है कि कर्ली कोष्ठक {...} हमेशा जरूरी नहीं हैं: जोड़ी और एक और बात यह है कि आप विचार करना चाह सकते arrow functions विशेष रूप से इस documentation का हिस्सा की उदार स्वभाव है। तो यह समारोह:

retOne =() => 1 

valid है और एक नया regex और अधिक कठिन बनाने बना सकता है। एक कामकाज मैंने सोचा था कि f.toString() से सभी घुंघराले ब्रैकेट को हटाएं:

str.replace(/[{}]/g, '')

और फिर वहां से regex test के साथ काम करें।

उम्मीद है कि अगर आप arrow functions चाहते हैं तो परीक्षण करने में सक्षम होने के लिए यह कुछ उपयोगी है।

1

यह आसान है कि केवल फ़ंक्शन को जांचें और फिर यदि यह खाली है या नहीं तो इसमें जांचें।
जांच इस Plunker
यहाँ पूर्ण काम कर कोड है:

function foo(a, b, c) {} 

function bar(a, b, c) { 
    var d; 
} 

function isEmpty(value) { 
    return (value == null || value.length === 0); 
} 

function check(test) { 
    var entire = test.toString(); 
    var body = entire.slice(entire.indexOf("{") + 1, entire.lastIndexOf("}")); 
    return body; 

} 
console.log(isEmpty(check(foo)), isEmpty(check(bar))); //return true false 
+0

यह फ़ंक्शन काम नहीं करता है अगर फ़ंक्शन टूस्ट्रिंग विधि को ओवरराइड करता है। –

+0

@AlexisTyler प्लंकर –

+0

@AlexisTyler को अपने प्रश्न में ओवरराइड करने के बारे में उल्लेख करने का उल्लेख है, फिर भी यदि आप इसे ओवरराइड करना चाहते हैं तो आप किसी अन्य फ़ंक्शन के अंदर डिफ़ॉल्ट toString फ़ंक्शन को सहेज सकते हैं –

2
Function.prototype.hasBody = function() { 
    return !/{\s*}$/.test(this.toString()); 
}; 
संबंधित मुद्दे

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