विस्मयादिबोधक चिह्न समारोह से पहले क्या करता है?


1242
!function () {}();

4
@ डीकम इसकी उपयोगिता इस उत्तर में बताई गई है: stackoverflow.com/questions/5422585/…
hectorct



7
@befzz बेहतर यह है कि इसे तुरंत लागू किए जाने वाले फंक्शन एक्सप्रेशन के रूप में संदर्भित किया जाए, क्योंकि यह लेख बाद में बताता है ("आत्म-क्रियान्वयन" का अर्थ है पुनरावृत्ति)
Zach Esposito

जवाबों:


2116

जावास्क्रिप्ट सिंटैक्स 101. यहाँ एक फ़ंक्शन घोषणा है :

function foo() {}

ध्यान दें कि कोई अर्धविराम नहीं है: यह सिर्फ एक फ़ंक्शन घोषणा है । आपको foo()वास्तव में फ़ंक्शन चलाने के लिए एक आह्वान की आवश्यकता होगी ।

अब, जब हम प्रतीत होता है अहानिकर विस्मयादिबोधक चिह्न जोड़ते हैं: !function foo() {}यह इसे एक अभिव्यक्ति में बदल देता है । यह अब एक फ़ंक्शन अभिव्यक्ति है

!अकेले ज़ाहिर है, समारोह को लागू नहीं करता है, लेकिन अब हम डाल सकते हैं ()अंत में: !function foo() {}()जो की तुलना में अधिक पूर्वता है !और तुरंत समारोह कहता है।

तो लेखक क्या कर रहा है प्रति फ़ंक्शन अभिव्यक्ति बाइट सहेज रहा है; यह लिखने का अधिक पठनीय तरीका यह होगा:

(function(){})();

अन्त में, !अभिव्यक्ति को सही बनाता है। ऐसा इसलिए है क्योंकि डिफ़ॉल्ट रूप से सभी IIFE रिटर्न undefined, जो हमें छोड़ देता है !undefinedजो है true। विशेष रूप से उपयोगी नहीं है।


229
+1। यह वास्तव में यहाँ सबसे अच्छा जवाब है, और दुख की बात है, शायद ही कभी उखाड़ा गया हो। जाहिर है, !रिटर्न बूलियन, हम सभी जानते हैं कि, लेकिन आप जो महान बिंदु बनाते हैं वह यह है कि यह फ़ंक्शन डिक्लेरेशन स्टेटमेंट को फ़ंक्शन एक्सप्रेशन में भी परिवर्तित करता है ताकि फंक्शन को तुरंत इसे कोष्ठकों में लपेटे बिना भी लागू किया जा सके। स्पष्ट नहीं है, और स्पष्ट रूप से कोडर का इरादा है।
gilly3

64
+1 यह एकमात्र उत्तर है जो वास्तव में आपको पता है कि आप ऐसा क्यों करना चाहते हैं, और कोई यह क्यों देखता है कि रिटर्न परिणाम की उपेक्षा से अधिक इसका उपयोग वारंट से प्रतीत होता है। एकटा संचालक! (यह भी ~, - और +) एक फ़ंक्शन घोषणा से अलग है, और अंत में () फ़ंक्शन को जगह में लागू करने के लिए अनुमति देता है। यह अक्सर मॉड्यूलर कोड लिखते समय चरों के लिए एक स्थानीय क्षेत्र / नाम स्थान बनाने के लिए किया जाता है।
टॉम ऑगर

65
एक और लाभ यह है कि! एक अर्ध-बृहदान्त्र सम्मिलन का कारण बनता है, इसलिए इस संस्करण के लिए एक फ़ाइल के साथ गलत तरीके से संक्षिप्त किया जाना असंभव है जो एक के साथ नहीं है। यदि आपके पास () फ़ॉर्म है, तो वह इसे पिछली फ़ाइल में परिभाषित की गई एक फ़ंक्शन कॉल पर विचार करेगा। मेरे एक सहकर्मी को टोपी की टिप।
जूरी ट्रिगलेव

5
@ कार्निक्स var foo =बयान / अभिव्यक्ति अस्पष्टता को तोड़ता है और आप बस लिख सकते हैं var foo = function(bar){}("baz");आदि
नील

6
यह आमतौर पर minification / uglification स्क्रिप्ट द्वारा किया जाता है, जहाँ हर एक बाइट मायने रखती है।
दिमा स्लिविन

367

कार्यक्रम:

function () {}

कुछ भी नहीं (या अपरिभाषित) देता है।

कभी-कभी हम किसी फ़ंक्शन को कॉल करना चाहते हैं जैसे ही हम इसे बनाते हैं। आप इसे आज़मा सकते हैं:

function () {}()

लेकिन यह एक में परिणाम है SyntaxError

!फ़ंक्शन के पहले ऑपरेटर का उपयोग करने के कारण इसे एक अभिव्यक्ति के रूप में माना जाता है, इसलिए हम इसे कॉल कर सकते हैं:

!function () {}()

यह इस मामले में true, फ़ंक्शन के वापसी मूल्य के विपरीत बूलियन को भी लौटाएगा , क्योंकि !undefinedहै true। यदि आप चाहते हैं कि वास्तविक रिटर्न वैल्यू कॉल का परिणाम हो, तो इसे इस तरह से करें:

(function () {})()

28
इसकी जरूरत किसे पड़ सकती है?
एंड्री

13
यह एकमात्र उत्तर है जो प्रश्न में मामले की व्याख्या करता है, ब्रावो!
एंड्री

14
आपका दूसरा कोड नमूना मान्य जावास्क्रिप्ट नहीं है। इसका उद्देश्य !फ़ंक्शन घोषणा को फ़ंक्शन अभिव्यक्ति में बदलना है, बस।
8 अक्टूबर को Skilldrick

8
@Andrey बूटस्ट्रैप ट्विटर इसका उपयोग सभी जावास्क्रिप्ट (jQuery) प्लगइन फाइलों में करता है। इस टिप्पणी को केवल अन्य लोगों के मामले में जोड़ने से भी यही प्रश्न हो सकता है।
अनमोल सराफ

2
d3.js !functionसिंटैक्स
क्रिस्टियन

65

एयरबीएनबी जावास्क्रिप्ट गाइड! पर चिह्नित फ़ंक्शन इनवोकेशन के लिए उपयोग करने के लिए एक अच्छा बिंदु है

आम तौर पर अलग-अलग फ़ाइलों (उर्फ मॉड्यूल) पर इस तकनीक का उपयोग करने के लिए विचार करें जो बाद में संक्षिप्त हो जाते हैं। यहाँ चेतावनी यह है कि फ़ाइलों को उन उपकरणों द्वारा समाहित किया जाना चाहिए, जो नई फ़ाइल को नई लाइन पर रखते हैं (जो कि अधिकतर कॉनकट टूल के लिए सामान्य व्यवहार है)। उस स्थिति में, उपयोग !करने में त्रुटि से बचने में मदद मिलेगी यदि पहले से अधिनियमित मॉड्यूल अनुगामी अर्धविराम से चूक गए थे, और फिर भी यह बिना किसी चिंता के उन्हें किसी भी क्रम में डालने की सुविधा देगा।

!function abc(){}();
!function bca(){}();

के रूप में ही काम करेंगे

!function abc(){}();
(function bca(){})();

लेकिन एक चरित्र बचाता है और मनमाना बेहतर दिखता है।

और जिस तरह से किसी के द्वारा +, -, ~, voidऑपरेटरों एक ही प्रभाव, समारोह लागू, सुनिश्चित करें के लिए के मामले में आपको लगता है कि समारोह वे अलग तरह से कार्य करेगा से वापस जाने के लिए कुछ उपयोग करना चाहते हैं की है।

abcval = !function abc(){return true;}() // abcval equals false
bcaval = +function bca(){return true;}() // bcaval equals 1
zyxval = -function zyx(){return true;}() // zyxval equals -1
xyzval = ~function xyz(){return true;}() // your guess?

लेकिन अगर आप एक फ़ाइल एक मॉड्यूल कोड जुदाई के लिए IIFE पैटर्न का उपयोग करते हैं और अनुकूलन के लिए कॉनैट टूल का उपयोग करते हैं (जो एक पंक्ति को एक फ़ाइल का काम बनाता है), तो निर्माण

!function abc(/*no returns*/) {}()
+function bca() {/*no returns*/}()

सुरक्षित कोड निष्पादन करेंगे, बहुत पहले कोड नमूने के समान।

यह एक त्रुटि पैदा करेगा क्योंकि जावास्क्रिप्ट एएसआई अपना काम करने में सक्षम नहीं होगा।

!function abc(/*no returns*/) {}()
(function bca() {/*no returns*/})()

एकतरफा ऑपरेटरों के बारे में एक नोट, वे समान काम करेंगे, लेकिन केवल मामले में, वे पहले मॉड्यूल में उपयोग नहीं करते थे। इसलिए वे इतने सुरक्षित नहीं हैं यदि आपके पास सहमति आदेश पर कुल नियंत्रण नहीं है।

यह काम:

!function abc(/*no returns*/) {}()
^function bca() {/*no returns*/}()

यह नहीं:

^function abc(/*no returns*/) {}()
!function bca() {/*no returns*/}()

3
दरअसल, उन अन्य प्रतीकों का समान प्रभाव नहीं होता है। हां, वे आपको वर्णित के रूप में एक फ़ंक्शन को कॉल करने की अनुमति देते हैं, लेकिन वे समान नहीं हैं। विचार करें: var foo =; function (bar) {कंसोल .ebug (बार); }("बल्ला"); इससे कोई फर्क नहीं पड़ता कि आपके सामने कौन से प्रतीक हैं, आपको अपने कंसोल में "बैट" मिलता है। अब, कंसोल जोड़ें ।ebug ("foo:", foo); - आपके द्वारा उपयोग किए जाने वाले प्रतीक के आधार पर आपको बहुत भिन्न परिणाम मिलते हैं। ! एक वापसी मूल्य को मजबूर करता है जो हमेशा वांछनीय नहीं होता है। मैं स्पष्टता और सटीकता के लिए ({}) () सिंटैक्स पसंद करता हूं।
कार्निक्स

29

यह बताता है कि क्या कथन गलत का मूल्यांकन कर सकता है। उदाहरण के लिए:

!false      // true
!true       // false
!isValid()  // is not valid

आप बूलियन के लिए एक मूल्य के लिए दो बार इसका उपयोग कर सकते हैं:

!!1    // true
!!0    // false

इसलिए, अधिक सीधे अपने प्रश्न का उत्तर दें:

var myVar = !function(){ return false; }();  // myVar contains true

संपादित करें: यह फ़ंक्शन घोषणा को फ़ंक्शन अभिव्यक्ति में बदलने का दुष्प्रभाव है। उदाहरण के लिए निम्न कोड मान्य नहीं है क्योंकि इसे एक फ़ंक्शन घोषणा के रूप में व्याख्या किया गया है जो आवश्यक पहचानकर्ता (या फ़ंक्शन नाम ) को याद कर रहा है :

function () { return false; }();  // syntax error

6
उन पाठकों के लिए स्पष्टता के लिए, जो तुरंत लागू किए गए फ़ंक्शन के साथ असाइनमेंट का उपयोग करना चाहते हैं, आपका उदाहरण कोड पसंद var myVar = !function(){ return false; }()को छोड़ सकता है और फ़ंक्शन सही तरीके से निष्पादित होगा और रिटर्न मान अछूता रहेगा। !var myVar = function(){ return false; }()
मार्क फॉक्स

1
स्पष्ट होने के लिए, आप बूलियन के साथ ज़बरदस्ती करने के लिए इसका एक बार उपयोग कर सकते हैं, क्योंकि यह एक तार्किक नहीं ऑपरेटर है। ० = सत्य, और! १ = असत्य। जावास्क्रिप्ट न्यूनतम उद्देश्यों के लिए, आप के trueसाथ !0और falseसाथ बदलना चाहते हैं !1। यह 2 या 3 अक्षर बचाता है।
1

9

जब हम जावास्क्रिप्ट मिनिफिकेशन करते हैं, तो यह डेटा की बाइट को बचाने के लिए होता है।

नीचे दिए गए अनाम फ़ंक्शन पर विचार करें

function (){}

ऊपर दिए गए को आत्म-आक्रमण फ़ंक्शन के रूप में बनाने के लिए हम आम तौर पर उपरोक्त कोड को बदल देंगे

(function (){}())

अब हमने फ़ंक्शन के अंत में (,)जोड़ने के अलावा दो अतिरिक्त वर्ण जोड़े ()जो फ़ंक्शन को कॉल करना आवश्यक है। न्यूनतमकरण की प्रक्रिया में हम आम तौर पर फ़ाइल का आकार कम करने पर ध्यान केंद्रित करते हैं। तो हम उपरोक्त फ़ंक्शन को भी लिख सकते हैं

!function (){}()

अभी भी दोनों आत्म-आक्रमण कार्य कर रहे हैं और हम एक बाइट भी बचाते हैं। 2 वर्णों के बजाय (,)हमने केवल एक वर्ण का उपयोग किया!


1
यह मददगार है क्योंकि अक्सर आप इसे minified js में देखेंगे
Name

5

! एक तार्किक नहीं ऑपरेटर है, यह एक बूलियन ऑपरेटर है जो इसके विपरीत कुछ उलट देगा।

यद्यपि आप फ़ंक्शन के पहले BANG (!) का उपयोग करके लागू फ़ंक्शन के कोष्ठकों को बायपास कर सकते हैं , फिर भी यह रिटर्न को उल्टा कर देगा, जो कि आप नहीं चाहते थे। जैसा कि एक IEFE के मामले में, यह अपरिभाषित होता है , जो कि उल्टे होने पर बूलियन सच हो जाता है।

इसके बजाय, यदि आवश्यक हो तो समापन कोष्ठक और BANG ( ! ) का उपयोग करें ।

// I'm going to leave the closing () in all examples as invoking the function with just ! and () takes away from what's happening.

(function(){ return false; }());
=> false

!(function(){ return false; }());
=> true

!!(function(){ return false; }());
=> false

!!!(function(){ return false; }());
=> true

अन्य ऑपरेटर जो काम करते हैं ...

+(function(){ return false; }());
=> 0

-(function(){ return false; }());
=> -0

~(function(){ return false; }());
=> -1

संयुक्त संचालक ...

+!(function(){ return false; }());
=> 1

-!(function(){ return false; }());
=> -1

!+(function(){ return false; }());
=> true

!-(function(){ return false; }());
=> true

~!(function(){ return false; }());
=> -2

~!!(function(){ return false; }());
=> -1

+~(function(){ return false; }());
+> -1

5

विस्मयादिबोधक चिह्न किसी भी फ़ंक्शन को हमेशा एक बूलियन वापस करता है।
अंतिम मान फ़ंक्शन द्वारा लौटाए गए मान का निषेध है।

!function bool() { return false; }() // true
!function bool() { return true; }() // false

छोड़ना !उपरोक्त उदाहरण में एक होगा सिंटैक्स त्रुटि

function bool() { return true; }() // SyntaxError

हालांकि, इसे प्राप्त करने का एक बेहतर तरीका होगा:

(function bool() { return true; })() // true

यह गलत है। !रनटाइम फ़ंक्शन को पार्स करने के तरीके को बदलता है। यह रनटाइम फ़ंक्शन को फ़ंक्शन एक्सप्रेशन (और डिक्लेरेशन नहीं) के रूप में व्यवहार करता है। यह ()सिंटैक्स का उपयोग करके फ़ंक्शन को तुरंत फ़ंक्शन को सक्षम करने के लिए सक्षम करता है । !फ़ंक्शन अभिव्यक्ति को लागू करने के परिणाम में खुद को (यानी नकार) भी लागू करेगा।
बेन एस्टन

3

IIFE लिखने का इसका एक और तरीका है (तुरंत-फ़ंक्शन फ़ंक्शन को आमंत्रित किया गया है)।

इसके लेखन का अन्य तरीका -

(function( args ) {})()

के समान

!function ( args ) {}();

खैर, यह बिल्कुल वैसा ही नहीं है; दूसरा फ़ॉर्म फ़ंक्शन कॉल के परिणाम को नकारता है (और फिर इसे दूर फेंक देता है, क्योंकि कोई मान असाइनमेंट नहीं है)। मैं कड़ाई से अधिक स्पष्ट (function (args) {...})()वाक्य रचना पसंद करूँगा और उस !functionफॉर्म को मिनिफिकेशन और ऑबफ्यूजन टूल पर छोड़ दूंगा।
टोबियास

-1

! जो कुछ भी आप एक परिणाम के रूप में उम्मीद कर रहे हैं, अर्थात (यदि आपके पास है) को नकारात्मक (विपरीत) करेंगे

var boy = true;
undefined
boy
true
!boy
false

जब आप कॉल boy, अपने परिणाम होगा true, लेकिन इस समय आप जोड़ना !जब बुला boy, यानी !boy, अपने परिणाम होगा false। कौन सा दूसरे शब्दों में आप का मतलब NotBoy , लेकिन इस बार यह मूल रूप से एक बूलियन परिणाम है, या तो trueया false

वह वही है जो !function () {}();अभिव्यक्ति के लिए होता है , केवल चलाने से function () {}();आपको एक त्रुटि दिखाई देगी, लेकिन !अपनी function () {}();अभिव्यक्ति के सामने सही जोड़ दें , यह विपरीत बनाता है function () {}();जो आपको वापस करना चाहिए true। उदाहरण नीचे देखा जा सकता है:

function () {}();
SyntaxError: function statement requires a name
!function () {}();
true
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.