मैं ES2015 में नामांकित तीर फ़ंक्शन कैसे लिखूं?


204

मेरे पास एक फ़ंक्शन है जिसे मैं ES6 में नए तीर सिंटैक्स में बदलने की कोशिश कर रहा हूं । यह एक नामित कार्य है:

function sayHello(name) {
    console.log(name + ' says hello');
}

क्या कोई ऐसा तरीका है जो इसे बिना var स्टेटमेंट के नाम दे सकता है:

var sayHello = (name) => {
    console.log(name + ' says hello');
}

जाहिर है, मैं इस फ़ंक्शन का उपयोग तब कर सकता हूं जब मैंने इसे परिभाषित किया है। कुछ इस प्रकार है:

sayHello = (name) => {
        console.log(name + ' says hello');
    }

क्या ईएस 6 में ऐसा करने का कोई नया तरीका है ?


3
फ़ंक्शन को कोई नाम नहीं देने के लिए तीर सिंटैक्स का बिंदु नहीं है ?
एस्ट्रोबी

64
जरूरी नहीं कि, तीर के कार्य में शंक्वाकार गुंजाइश बनी रहे इसलिए नाम के कार्यों (स्टैक ट्रेस के लिए उपयोगी) का उत्पादन करने के लिए एक शॉर्टहैंड होता है जिसमें लेक्सिकल स्कोप बहुत उपयोगी होगा
मैट स्टाइल्स

6
दूसरा स्निपेट क्या गलत है?
बेर्गी जूल

आप निश्चित रूप से फ़ंक्शन के शरीर के अंदर एक निर्दिष्ट नाम का संदर्भ दे सकते हैं: var sayHello = (नाम) => {कंसोल.लॉग (SayHello); }; और पुनरावर्ती कार्यों के मामले में, आप अक्सर ऐसा ही करेंगे। एक सुपर उपयोगी उदाहरण नहीं है, लेकिन यहां एक फ़ंक्शन है जो स्वयं लौटता है अगर उसे अपना तर्क नहीं मिलता है: var sayHello = (नाम = = नाम; कंसोल .log (नाम + 'हैलो कहता है)): sayHello; sayHello () ( 'खुलकर'); // -> "फ्रैंक कहता है हैलो"
Dtipson

4
प्रश्न का शीर्षक अपनी सामग्री की तुलना में बेहद भ्रामक है, क्योंकि आपने तीर के कार्यों को नाम देने के तरीके को खारिज कर दिया है (जो दूसरा स्निपेट है)।
टीजे क्राउडर

जवाबों:


211

मैं ES2015 में नामांकित तीर फ़ंक्शन कैसे लिखूं?

आप इसे अपने प्रश्न के रूप में खारिज कर देते हैं: आप इसे किसी असाइनमेंट या प्रॉपर्टी इनिशियलाइज़र के दाईं ओर रखते हैं, जहाँ चर या प्रॉपर्टी के नाम का उपयोग जावास्क्रिप्ट इंजन द्वारा एक नाम के रूप में किया जा सकता है। ऐसा करने का कोई अन्य तरीका नहीं है, लेकिन ऐसा करना सही है और पूरी तरह से विनिर्देश द्वारा कवर किया गया है।

कल्पना के अनुसार, इस समारोह का एक सही नाम है sayHello:

var sayHello = name => {
    console.log(name + ' says hello');
};

इसे असाइनमेंट ऑपरेटर्स> रनटाइम सेमेंटिक्स: इवैलुएशन में परिभाषित किया गया है, जहां यह एब्सट्रैक्ट SetFunctionNameऑपरेशन कहता है (यह कॉल अभी चरण १.e.iii में है)।

समान रूप से, रनटाइम सेमेंटिक्स: प्रॉपर्टीफाइनेशन इवैल्यूएशन कॉल SetFunctionNameऔर इस प्रकार इस फ़ंक्शन को एक सही नाम देता है:

let o = {
    sayHello: name => {
        console.log(`${name} says hello`);
    }
};

आधुनिक इंजन पहले से ही इस तरह के बयानों के लिए फ़ंक्शन का आंतरिक नाम सेट करते हैं; एज अभी भी इसे nameरनटाइम फ्लैग के पीछे फ़ंक्शन इंस्टेंस पर उपलब्ध करा रहा है।

उदाहरण के लिए, Chrome या Firefox में, वेब कंसोल खोलें और फिर इस स्निपेट को चलाएं:

"use strict";
let foo = () => { throw new Error(); };
console.log("foo.name is: " + foo.name);
try {
  foo();
} catch (e) {
  console.log(e.stack);
}

Chrome 51 और ऊपर और फ़ायरफ़ॉक्स 53 और उससे ऊपर (और एज 13 और ऊपर एक प्रयोगात्मक ध्वज के साथ), जब आप उसे चलाते हैं, तो आप देखेंगे:

foo.name है: फू
त्रुटि
    फू पर (http://stacksnippets.net/js:14:23)
    http://stacksnippets.net/js:17:3 पर

नोट foo.name is: fooऔर Error...at foo

Chrome 50 और उससे पहले, फ़ायरफ़ॉक्स 52 और उससे पहले और ऐज को प्रयोगात्मक झंडे के बिना, आप इसके बजाय देखेंगे क्योंकि उनके पास Function#nameसंपत्ति नहीं है (अभी तक):

foo.name है: 
त्रुटि
    फू पर (http://stacksnippets.net/js:14:23)
    http://stacksnippets.net/js:17:3 पर

ध्यान दें कि नाम से याद आ रही है foo.name is:, लेकिन यह है स्टैक ट्रेस में दिखाया गया है। यह सिर्फ इतना है कि वास्तव में फ़ंक्शन पर name संपत्ति को लागू करना कुछ अन्य ES2015 सुविधाओं की तुलना में कम प्राथमिकता थी; क्रोम और फ़ायरफ़ॉक्स अब यह है; एज में एक ध्वज के पीछे है, संभवतः यह ध्वज के पीछे नहीं होगा।

जाहिर है, मैं इस फ़ंक्शन का उपयोग तब कर सकता हूं जब मैंने इसे परिभाषित किया है

सही बात। तीर फ़ंक्शन के लिए कोई फ़ंक्शन घोषणा सिंटैक्स नहीं है , केवल फ़ंक्शन एक्सप्रेशन सिंटैक्स है, और फ़ंक्शन- एक्सप्रेशन नाम की पुरानी शैली में नाम के बराबर कोई तीर नहीं है var f = function foo() { };। तो इसके बराबर नहीं है:

console.log(function fact(n) {
    if (n < 0) {
        throw new Error("Not defined for negative numbers");
    }
    return n == 0 ? 1 : n * fact(n - 1);
}(5)); // 120

आपको इसे दो अभिव्यक्तियों में तोड़ना होगा (मेरा तर्क है कि आपको वैसे भी करना चाहिए ) :

let fact = n => {
    if (n < 0) {
      throw new Error("Not defined for negative numbers.");
    }
    return n == 0 ? 1 : n * fact(n - 1);
};
console.log(fact(5));

बेशक, अगर आपको इसे रखना है जहां एक एकल अभिव्यक्ति की आवश्यकता है, तो आप हमेशा कर सकते हैं ... एक तीर फ़ंक्शन का उपयोग करें:

console.log((() => {
    let fact = n => {
        if (n < 0) {
            throw new Error("Not defined for negative numbers.");
        }
        return n == 0 ? 1 : n * fact(n - 1);
    };
    return fact(5);
})()); // 120

मैं यह नहीं कह रहा हूं कि यह सुंदर है, लेकिन यह काम करता है अगर आप बिल्कुल, सकारात्मक रूप से एक एकल अभिव्यक्ति आवरण की आवश्यकता है।


मैं नाम को सेट होने से कैसे रोक सकता हूं (जैसे पुराने इंजन में)?
trusktr

1
@trusktr: मैं यह नहीं देख सकता कि आप क्यों करना चाहते हैं, लेकिन यदि आप इसे रोकना चाहते हैं: तो ऊपर वाली बात न करें। उदाहरण के लिए, जबकि let f = () => { /* do something */ };फ़ंक्शन को एक नाम असाइन करता है, let g = (() => () => { /* do something */ })();नहीं।
टीजे क्राउडर

यही मैंने खत्म किया। मुझे अपनी आंतरिक विरासत लाइब्रेरी के द्वारा अनाम कक्षाओं को उत्पन्न करने की बजाय आंतरिक चर के नामों से गुमनाम होना चाहिए, जो कि मेरी कक्षा विरासत पुस्तकालय के उपयोगकर्ता के बारे में सोचने की आवश्यकता नहीं है, और मुझे नाम देखने के लिए अंतिम उपयोगकर्ता चाहिए केवल अगर वे कक्षा के लिए एक नाम प्रदान करते हैं। ( github.com/trusktr/lowclass )
trusktr

4
@trusktr: उनके द्वारा किया गया एक अपवाद आपके उद्देश्यों के लिए उपयुक्त हो सकता है, फिर: यदि आप किसी मौजूदा ऑब्जेक्ट पर किसी संपत्ति को कोई फ़ंक्शन असाइन करते हैं, तो नाम सेट नहीं है: o.foo = () => {};फ़ंक्शन को कोई नाम नहीं देता है। यह जानबूझकर सूचना रिसाव को रोकने के लिए किया गया था
टीजे क्राउडर

86

नहीं। तीर सिंटैक्स अनाम कार्यों के लिए एक कमी है। अनाम कार्य, अच्छी तरह से, अनाम हैं।

नामित कार्यों को functionकीवर्ड के साथ परिभाषित किया गया है ।


16
जैसा कि @ DenysSéguret ने कहा था, अनाम कार्यों के लिए कोई कमी नहीं है । आपको एक हार्ड बाइंडेड फंक्शन मिलेगा । आप बेहतर परिणाम को समझने के लिए यहाँ bit.do/es2015-arrow ट्रांसप्‍लेड परिणाम देख सकते हैं ...
sminutoli

16
इस उत्तर का पहला शब्द पूछे गए प्रश्न के लिए सही है क्योंकि ओपी ने एक तीर फ़ंक्शन का नाम देने के तरीके से इनकार किया है। लेकिन उत्तर का शेष केवल गलत है। जहां अमूर्त SetFunctionNameऑपरेशन का उपयोग किया जाता है, उसके लिए विनिर्देश में देखें । let a = () => {};एक नामित फ़ंक्शन (नाम है a) दोनों को कल्पना और आधुनिक इंजन के अनुसार परिभाषित करता है ( देखने के लिए इसमें कोई त्रुटि फेंकें); वे अभी nameसंपत्ति का समर्थन नहीं करते हैं (लेकिन यह कल्पना में है और वे अंततः वहां पहुंचेंगे)।
टीजे क्राउडर

4
@ DenysSéguret: आप बस उन्हें नाम दे सकते हैं, यह कल्पना में है। आप इसे उस तरह से करते हैं जैसे ओपी प्रश्न में खारिज करता है, जो फ़ंक्शन (न केवल चर) को एक सही नाम देता है।
TJ Crowder

5
@TJCrowder जानकारी के उस बिट के लिए, और आपके उपयोगी उत्तर के लिए धन्यवाद । मुझे यह (बहुत अजीब) सुविधा नहीं पता थी।
डेनसिटी सेगुरेट

4
यह उत्तर सही नहीं है। इस प्रश्न का उत्तर सही ढंग से @TJCrowder द्वारा दिया गया था
Drenai

44

यदि 'नाम' से है, तो इसका मतलब है कि आप .nameअपने एरो फंक्शन की संपत्ति सेट करना चाहते हैं, तो आप किस्मत में हैं।

यदि एक असाइनमेंट एक्सप्रेशन के दाईं ओर एक एरो फंक्शन परिभाषित किया गया है, तो इंजन लेफ्ट-हैंड-साइड पर नाम लेगा और एरो फंक्शन के सेट करने के लिए इसका उपयोग करेगा .name, जैसे

var sayHello = (name) => {
    console.log(name + ' says hello');
}

sayHello.name //=== 'sayHello'

यह कहने के बाद, आपका प्रश्न अधिक प्रतीत होता है 'क्या मुझे तीर फहराने के लिए एक समारोह मिल सकता है?' उस एक का जवाब एक बड़ा राजभाषा है "" नहीं ", मुझे डर है।


1
क्रोम के वर्तमान संस्करण में, कम से कम, sayHello.name अभी भी "" है; ध्यान दें कि सभी फ़ंक्शंस की तरह, SayHello एक ऑब्जेक्ट है, इसलिए यदि आप चाहें तो आप इसके लिए मनमाने गुणों को परिभाषित कर सकते हैं। आप "नाम" नहीं लिख सकते क्योंकि यह केवल पढ़ने के लिए है, लेकिन आप कह सकते हैं। यकीन नहीं है कि क्या आप हालांकि हो जाता है, क्योंकि आप ऐसा नहीं कर सकते / संदर्भ कि समारोह के शरीर के भीतर।
२२:२० बजे द्वादशी

2
मैं गलत था: जबकि नाम सीधे रूप से उपलब्ध नहीं है, आप इसे इस तरह कॉन्फ़िगर कर सकते हैं: Object.defineProperty (SayHello, 'name', {value: 'sayHello'})
Dtipson

1
"यदि कोई तीर फ़ंक्शन दाईं ओर स्थित है [..]" तो इसके लिए स्रोत क्या है? मैं इसे कल्पना में नहीं ढूँढ सकता। बस उद्धरण की आवश्यकता है।
गजस

@Dtipson: ऐसा इसलिए है क्योंकि आधुनिक इंजन अभी तक nameहर जगह संपत्ति स्थापित करने के लिए लागू नहीं हुए हैं, जबकि ES2015 कल्पना उन्हें करने की आवश्यकता है; वे इसे प्राप्त करेंगे। यह क्रोम के लिए अनुपालन सूची पर अंतिम चीजों में से एक है और यहां तक ​​कि क्रोम 50 के पास भी नहीं है (क्रोम 51 अंत में होगा)। विवरण । लेकिन ओपी ने विशेष रूप से ऐसा करने से इनकार किया (विचित्र रूप से)।
टीजे क्राउडर

क्या मैं इस नाम को प्राप्त कर सकता हूं? मैंने इसे ओवरराइड करने की कोशिश की, लेकिन फिर मुझे नहीं पता कि फ़ंक्शन बॉडी को कैसे एक्सेस करना है।
क्वर्टी

0

ऐसा प्रतीत होता है कि ES7 के साथ यह संभव होगा: https://babeljs.io/blog/2015/06/07/react-on-es6-plus#arrow-functions

उदाहरण दिया गया है:

class PostInfo extends React.Component {
  handleOptionsButtonClick = (e) => {
    this.setState({showOptionsModal: true});
  }
}

ES6 एरो फ़ंक्शंस का शरीर उसी लेक्सिकल को साझा करता है जो उन्हें घेरे हुए कोड के रूप में होता है, जो ईएस 7 संपत्ति इनिशियलाइज़र के स्कोप होने के तरीके के कारण हमें वांछित परिणाम प्राप्त करता है।

ध्यान दें कि बैबल के साथ यह काम करने के लिए मुझे सबसे प्रयोगात्मक ES7 चरण 0 सिंटैक्स को सक्षम करने की आवश्यकता थी। मेरे webpack.config.js फ़ाइल में मैंने बाबेल लोडर को इस तरह अद्यतन किया:

{test: /\.js$/, exclude: /node_modules/, loader: 'babel?stage=0'},

6
यह वास्तव में एक नामित तीर फ़ंक्शन नहीं है। यह कंस्ट्रक्टर में उदाहरण के तरीके बनाने के लिए एक शॉर्टकट है, और मुझे आश्चर्य है कि यह यहां कैसे प्रासंगिक है?
बरगी

हाय @Bergi, मुझे यकीन नहीं है कि यह मूल लेखक का इरादा था, लेकिन मैं ऑब्जेक्ट के रूप में इस गुंजाइश के साथ एक नामित फ़ंक्शन बनाने की कोशिश कर रहा था। यदि हम इस तकनीक का उपयोग नहीं करते हैं, और हम चाहते हैं कि उपयुक्त गुंजाइश हो तो हमें इसे क्लास कंस्ट्रक्टर में डालना होगा। this.handleOptionsButtonClick = this.handleOptionsButtonClick.bind(this);
हमीश करी

8
उह, आप बस आसानी से उपयोग कर सकते हैं constructor() { this.handleOptionsButtonClick = (e) => {…}; }जो आपके उत्तर में कोड के बराबर है लेकिन पहले से ही ES6 में काम करता है। उपयोग करने की आवश्यकता नहीं है .bind
बरगी

1
Btw, मुझे लगता है कि आप " thisसंदर्भ" (उदाहरण) विधि "और" गुंजाइश "के साथ" संदर्भ "के साथ भ्रमित कर रहे हैं
बेर्गी

1
@ नोट: हाँ, आप कर सकते हैं; Jörg गलत है। let a = () => {};एक नामित तीर फ़ंक्शन को परिभाषित करता है aविवरण
टीजे क्राउडर

0

वास्तव में यह तीर के कार्यों को नाम देने का एक तरीका है (कम से कम 77 क्रोम के रूप में ...) ऐसा करना है:

"use strict";
let fn_names = {};
fn_names.foo = () => { throw new Error(); };
console.log("foo.name is: " + foo.name);
try {
  foo();
} catch (e) {
  console.log(e.stack);
}

यहां छवि विवरण दर्ज करें


सैद्धांतिक रूप से एक बैबल मैक्रो बना सकता है fn('yourName', ()=>{}), जो 100% सही एरो फ़ंक्शन सिमेंटिक्स बनाए रख सकता है, या बेहतर "एरो फ़ंक्शन सिंटैक्स" के लिए एक बैबल प्लगइन fn yourName() => {}। इनमें से कोई भी ऊपर दिए गए कोड को संकलित करेगा। मुझे लगता है कि तीर नाम BADA55
डेविन जी रोड

-1

एरो फंक्शन लिखने के लिए आप bellow का उदाहरण दे सकते हैं, जहाँ मेरे पास LoginClass नाम की एक क्लास है और इस क्लास के अंदर मैंने फंक्शन नाम से एक ऐरो लिखा है , जिसका नाम है successAuth LoginClass {

    constructor() {

    }

    successAuth = (dataArgs)=> { //named arow function

    }

}

1
यह हमेशा बेहतर होता है कि आप एक कोड को एक उत्तर के रूप में पोस्ट कर रहे हों, ताकि यह आगंतुकों को यह समझने में मदद करे कि यह एक अच्छा उत्तर क्यों है।
अबारिसोन

यह वही करता है जो ओपी ने कहा था कि वह ऐसा नहीं करना चाहता है, और इस प्रस्ताव पर निर्भर करता है जो केवल स्टेज 2 पर है और शायद ES2017 बनाने के लिए भी नहीं जा रहा है (लेकिन मुझे लगता है कि यह ES2018 बनाने की संभावना है, और ट्रांसपिलर्स ने इसका समर्थन किया है महीनों के लिए)। यह प्रभावी रूप से कई पिछले उत्तरों की नकल करता है, जो उपयोगी नहीं है।
टीजे क्राउडर

-2

यह ES6 है

हाँ, मुझे लगता है कि आप इसके बाद कुछ इस तरह हैं:

const foo = (depth) => {console.log("hi i'm Adele")}
foo -> // the function itself
foo() -> // "hi i'm Adele"

मैंने इस उदाहरण की कोशिश की, यह ठीक काम करता है। नकारात्मक वोट देने का कोई अच्छा कारण? क्या यह उपयोग किसी भी अवांछित दुष्प्रभाव को पैदा करता है या क्या मुझे कोई महत्वपूर्ण बिंदु याद आ रहा है? मेरे संदेह को स्पष्ट करने में आपकी मदद की सराहना की जाएगी।
फुलमून

@GaneshAdapa: मुझे उम्मीद है कि डाउनवोट्स हैं क्योंकि यह वही करने का सुझाव दे रहा है जो ओपी ने कहा था कि वह आगे कोई जानकारी दिए बिना वह करना चाहता था।
टीजे क्राउडर

-2

फ़ंक्शन बनाने के लिए आप फंक्शन पार्ट और एरो पार्ट को छोड़ सकते हैं। उदाहरण:

 class YourClassNameHere{

   constructor(age) {
     this.age = age;
   }

   foo() {
     return "This is a function with name Foo";
   }

   bar() {
     return "This is a function with name bar";
   }

 }

let myVar = new YourClassNameHere(50);
myVar.foo();
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.