ES6 ने तुरंत तीर फ़ंक्शन को लागू किया


149

यह Node.jsकंसोल में काम क्यों करता है (4.1.1 और 5.3.0 में परीक्षण किया गया) लेकिन ब्राउज़र (क्रोम में परीक्षण) में काम नहीं करता है? यह कोड ब्लॉक एक अनाम फ़ंक्शन बनाता है और लॉग इन करना चाहिए Ok

() => {
  console.log('Ok');
}()

इसके अलावा, जबकि उपरोक्त नोड में काम करता है, यह काम नहीं करता है:

n => {
  console.log('Ok');
}()

और न ही यह:

(n) => {
  console.log('Ok');
}()

यह अजीब है कि जब पैरामीटर जोड़ा जाता है तो यह वास्तव SyntaxErrorमें तुरंत-आह्वान वाले भाग पर फेंकता है ।


8
अच्छा प्रश्न। दोनों
मानकीकृत

2
ब्याज से बाहर, (n => { console.log("Ok"); })();काम करता है ?
कोडिंगइंट्रिग्यू

हाँ (n => { console.log("Ok"); })(), क्रोम देव कंसोल में भी काम करता है
XCS

और इसलिए, 3 साल बाद, जवाब है? निश्चित रूप से नीचे दिए गए 3 उत्तरों में से एक को स्वीकार किया जाना चाहिए?
joedotnot 8

@joedotnot मुझे स्पष्ट उत्तर नहीं मिला, ज्यादातर यह Node.js. में एक अजीब कार्यान्वयन था। ऐसा लगता है Node.jsकि पहले संस्करण का नवीनतम संस्करण अब काम नहीं कर रहा है।
XCS

जवाबों:


194

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

(() => {
  console.log('Ok');
})()

IIFE के समकक्ष है

(function(){
   console.log('Ok')
})();

और संभावित कारण यह Node.js में काम करता है, लेकिन क्रोम में नहीं है क्योंकि इसका पार्सर इसे एक आत्मघाती कार्य के रूप में व्याख्या करता है, जैसे कि यह

function() { console.log('hello'); }();

Node.jsयह ठीक काम करता है यह एक अभिव्यक्ति और क्रोम और फ़ायरफ़ॉक्स है और अधिकांश ब्राउज़र इस तरह से व्याख्या करते हैं। आपको इसे मैन्युअल रूप से लागू करने की आवश्यकता है।

फ़ंक्शन अभिव्यक्ति की अपेक्षा करने के लिए पार्सर को बताने के लिए सबसे व्यापक रूप से स्वीकृत तरीका यह है कि इसे केवल Parens में लपेटें, क्योंकि JavaScript में, parens स्टेटमेंट नहीं दे सकते। इस बिंदु पर, जब पार्सर फ़ंक्शन कीवर्ड का सामना करता है, तो इसे फ़ंक्शन अभिव्यक्ति के रूप में पार्स करना जानता है न कि फ़ंक्शन की घोषणा।

पैरामीरिज्ड संस्करण के बारे में , यह काम करेगा।

((n) => {
  console.log('Ok');
})()

4
पहला उदाहरण काम करता है Node.jsऔर वास्तव में मूल्य को लॉग करता है। मेरा सवाल यह है कि यह काम क्यों करता है? और जब मैं पैरामीटर जोड़ता हूं तो यह क्यों नहीं होता है?
XCS

1
मैं IIFEएस से बहुत परिचित हूं और अपने कोड को ठीक करना जानता हूं। मैं बस उत्सुक था कि, उदाहरण के लिए, पैरामीटर के बिना काम करने पर मेरा IIFEकाम नहीं करता nहै, भले ही यह पैरामीटर के बिना काम करता हो।
XCS

3
मैंने डाउनवोट नहीं किया, लेकिन सवाल यह है कि जब पैरामीटर एक पैरामीटर के बिना सटीक समान परिभाषा करता है, तो नोड में पैरामीटर संस्करण काम नहीं करता है - यह अनाम कार्यों के नोड / क्रोम कार्यान्वयन के बीच अंतर नहीं पूछ रहा है
कोडिंगइंट्रिग्यू

1
इसका अच्छा पता है, लेकिन यह इस सवाल का जवाब नहीं देता है, जैसा कि पहले उल्लेख किया गया है, - क्यों पैरामीटर पैरामीटर नोड में काम नहीं करता है जब एक पैरामीटर के बिना सटीक एक ही परिभाषा करता है
jkris 23'16

लेकिन function(){}()तीर के कार्यों में बराबर क्या है ? अगर मैं चाहता हूं कि फंक्शन ऑब्जेक्ट एक्सपेक्टेड फंक्शन एक्सप्रेशन उसके खिलाफ प्रोटेक्ट करें।
दिबाबा

18

इनमें से कोई भी बिना कोष्ठक के काम नहीं करना चाहिए।

क्यों?

क्योंकि युक्ति के अनुसार:

  1. ArrowFunction है के तहत सूचीबद्ध AssignmentExpression
  2. एक की एलएचएस CallExpression एक होना चाहिए MemberExpression , SuperCall या CallExpression

तो ए ArrowFunction एक की एलएचएस पर नहीं हो सकता CallExpression


इसका प्रभावी ढंग से अर्थ कैसे =>समझा जाना चाहिए, यह है कि यह एक ही प्रकार के स्तर पर काम करता है जैसे असाइनमेंट ऑपरेटर =, +=आदि।

अर्थ

  • x => {foo}() नहीं बन जाता है(x => {foo})()
  • दुभाषिया इसकी व्याख्या करने की कोशिश करता है x => ({foo}())
  • इस प्रकार यह अभी भी एक SyntaxError है
  • तो दुभाषिया तय करता है कि (गलत हुआ होगा और एक सिंटेक्स एरर फेंकता है

यहाँ इसके बारे में बाबेल पर एक बग भी था।


वे कुछ मान्य बिंदु हैं, लेकिन अगर मैं () => ({console.log('Ok')}())इसके साथ पहले, काम करने वाले संस्करण को बदलने की कोशिश करता हूं: यह अब काम नहीं करता है। तो यह वास्तव में इसे इस तरह से व्याख्या नहीं करता है।
एक्ससीएस

@ क्रिसी यह एक मान्य एरो फंक्शन उत्पादन नहीं है। यह सोचता है कि आप ऑब्जेक्ट शाब्दिक (कोष्ठक द्वारा संलग्न) के साथ एक ऑब्जेक्ट बनाने की कोशिश कर रहे हैं और console.log(...)एक मान्य कुंजी नाम नहीं है।
thefourtheye

@Cristy: हां, मुझे लगता है कि ऊपर ("अर्थ" बिट) की व्याख्या वाला हिस्सा काफी सही नहीं हो सकता है, लेकिन विनिर्देश के हिस्से जहां तक ​​मैं बता सकता हूं। : यह भी त्रुटि है कि मैं वी 8 से मिलता है फिट बैठता है SyntaxError: Unexpected token ((पर इंगित (में ()अंत में, नहीं (में console.log(...))।
TJ Crowder

@TJCrowder आप सही हैं, मैं त्रुटि संदेश को बदल देता हूं और मैं जो कह रहा हूं, उसे मैं (समाप्त कर दूंगा (जो कि व्याख्या करने का कारण नहीं है, यानी एक वैध व्याख्या खोजने के प्रयासों को समाप्त करने के बाद दुभाषिए को छोड़ देना चाहिए और चला जाता है) "यह गलत होना चाहिए"), जो वैसे भी गलत हो सकता है क्योंकि मुझे नहीं पता कि दुभाषिया वास्तव में कैसे लिखा गया है
पॉल एस।

मैं सोच रहा था कि क्या यह इस स्थिति में एक वैध टोकन नहीं है, तो क्या यह अर्ध उपनिवेश डालने की कोशिश नहीं करेगा?
thefourtheye

2

आपके द्वारा इस तरह की समस्याएं देखने का कारण यह है कि कंसोल स्वयं उस संदर्भ के वैश्विक दायरे का अनुकरण करने का प्रयास करता है जिसे आप वर्तमान में लक्षित कर रहे हैं। यह कंसोल में लिखने वाले कथनों और अभिव्यक्तियों से वापसी मूल्यों को पकड़ने की कोशिश करता है, ताकि परिणाम के रूप में दिखाई दे। उदाहरण के लिए, लें:

> 3 + 2
< 5

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

यह भी एक कारण है कि स्क्रिप्ट में कुछ नंगे ES6 कोड ठीक काम करते हैं, लेकिन क्रोम देव टूल्स कंसोल में नहीं हैं।

नोड और क्रोम कंसोल में इसे निष्पादित करने का प्रयास करें:

{ let a = 3 }

नोड या एक <script>टैग में यह ठीक काम करता है, लेकिन कंसोल में, यह देता है Uncaught SyntaxError: Unexpected identifier। यह आपको स्रोत के लिए एक लिंक भी देता है, VMxxx:1जिसके रूप में आप मूल्यांकन किए गए स्रोत का निरीक्षण करने के लिए क्लिक कर सकते हैं, जो इस प्रकार है:

({ let a = 3 })

तो इसने ऐसा क्यों किया?

उत्तर यह है कि इसे आपके कोड को एक अभिव्यक्ति में बदलने की आवश्यकता है ताकि परिणाम कॉलर को वापस किया जा सके और कंसोल में प्रदर्शित किया जा सके। आप इसे कोष्ठक में कथन को लपेटकर कर सकते हैं, जो इसे एक अभिव्यक्ति बनाता है, लेकिन यह ब्लॉक को सिंटैक्टिक रूप से गलत बनाता है (एक अभिव्यक्ति में ब्लॉक घोषणा नहीं हो सकती है)।

कंसोल कोड के बारे में होशियार होकर इन बढ़त के मामलों को ठीक करने की कोशिश करता है, लेकिन यह इस उत्तर के दायरे से परे है, मुझे लगता है। आप यह देखने के लिए बग दर्ज कर सकते हैं कि कुछ ऐसा है जिसे वे ठीक करने पर विचार करेंगे।

यहाँ कुछ इसी तरह का एक अच्छा उदाहरण है:

https://stackoverflow.com/a/28431346/46588

अपने कोड का काम करने का सबसे सुरक्षित तरीका यह सुनिश्चित करना है कि इसे एक अभिव्यक्ति के रूप में चलाया जा सकता है और SyntaxErrorस्रोत लिंक का निरीक्षण करके यह देखने के लिए कि वास्तविक निष्पादन कोड क्या है और इससे इंजीनियर को एक समाधान उल्टा पड़ता है। आमतौर पर इसका अर्थ है रणनीतिक रूप से रखे गए कोष्ठकों की एक जोड़ी।

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


1
यह पूरे बिंदु है, मैं पैरामीटर के बारे में परवाह करता हूं, लेकिन यह पैरामीटर सेट के साथ काम नहीं करता है।
XCS

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

0

मैंने इस तरह एक सवाल पूछा:

भूल जाओ मैं इस सवाल है: एक #IIFE पैटर्न का उत्पादन करने के लिए हम एक फ़ंक्शन घोषणा के चारों ओर parans का उपयोग करके इसे फ़ंक्शन अभिव्यक्ति में परिवर्तित करते हैं और फिर इसे लागू करते हैं। अब एरो फंक्शन IIFEs में, हमें पैरन्स की आवश्यकता क्यों है ?! क्या तीर फ़ंक्शन पहले से ही डिफ़ॉल्ट रूप से एक अभिव्यक्ति नहीं है ?!

और यह काइल सिम्पसन का जवाब है:

एक तीर समारोह है एक expr, लेकिन हम आसपास कोष्ठक b / c "ऑपरेटर पूर्वता" (sorta) की आवश्यकता है, तो अंतिम कोष्ठक तीर Iife पूरे समारोह के लिए लागू आह्वान और उसके शरीर के अभी पिछले टोकन के लिए नहीं करने के लिए कि ।

x => console.log(x)(4)

बनाम

(x => console.log(x))(4)

- getify (@getify) 12 जून, 2020


मेरा सवाल यह था कि इसने कुछ कंपाइलरों पर काम किया और दूसरों पर नहीं।
XCS

ऐसा इसलिए है क्योंकि अलग-अलग संकलक अलग-अलग ब्राउज़रों की तरह कुछ विवरणों में भिन्न व्यवहार करते हैं, बेशक अलग-अलग संकलक हैं
इरशाद कादरी

आप सही हैं, वे अलग तरह से व्यवहार करते हैं, लेकिन जावास्क्रिप्ट स्पेक्स उन सभी के लिए समान हैं। मैं उत्सुक था कि कौन सा सही था, जेएस कल्पना इस मामले के बारे में क्या कहती है और विशेष रूप से यह कैसे हो सकता है कि यह तर्क के बिना काम करता है लेकिन तर्क के बिना नहीं। मैं एक अधिक तकनीकी प्रतिक्रिया की तलाश में था।
XCS

आपका उदाहरण बहुत स्पष्ट है, पहले मामले में इसे वास्तव में कॉल करना चाहिए console.log(x)(4)
XCS

मैं यहां केवल अनुमान लगा रहा हूं, लेकिन मुझे लगता है कि इसे इस तरह समझाना बहुत उचित है: एरो फंक्शन एक्सप्रेशन में जब हम एक पैरामीटर का उपयोग नहीं करते हैं तो हमें परेंस का उपयोग करना चाहिए और यह इंजन के लिए बहुत स्पष्ट करता है कि यह एक एरो है फ़ंक्शन अभिव्यक्ति, लेकिन जब हमारे पास एक एकल पैरामीटर होता है, तो परेंस मनमाने ढंग से होते हैं, जो कि बहुत स्पष्ट नहीं हो सकता है कि यह एक फ़ंक्शन है और उस इंजन को भ्रमित करता है, इस भ्रम को हल करने के लिए हमें पूरे फ़ंक्शन एक्सप्रेशन के चारों ओर एक जोड़े को रखना होगा
इरशाद कादरी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.