प्रस्ताव के अनुसार , तीर का उद्देश्य "पारंपरिक के कई सामान्य दर्द बिंदुओं को संबोधित करना और हल करना" है Function Expression। वे जुड़ कर मामलों सुधार करने के उद्देश्य thislexically और संक्षिप्त वाक्य रचना की पेशकश की।
तथापि,
- कोई लगातार
thisशाब्दिक रूप से बाँध नहीं सकता है
- एरो फ़ंक्शन सिंटैक्स नाजुक और अस्पष्ट है
इसलिए, तीर फ़ंक्शंस भ्रम और त्रुटियों के लिए अवसर पैदा करते हैं, और functionविशेष रूप से प्रतिस्थापित जावास्क्रिप्ट प्रोग्रामर की शब्दावली से बाहर रखा जाना चाहिए ।
शाब्दिक अर्थ के बारे में this
this समस्याग्रस्त है:
function Book(settings) {
this.settings = settings;
this.pages = this.createPages();
}
Book.prototype.render = function () {
this.pages.forEach(function (page) {
page.draw(this.settings);
}, this);
};
एरो फ़ंक्शंस उस समस्या को ठीक करने का इरादा रखते हैं जहां हमें thisकॉलबैक के अंदर की संपत्ति तक पहुंचने की आवश्यकता होती है । वहां पहले से ही है कि ऐसा करने के लिए कई तरीके हैं: एक आवंटित कर सकते हैं thisएक चर, उपयोग करने के लिए bind, या 3 तर्क पर उपलब्ध का उपयोग Arrayकुल तरीकों। अभी तक तीर सबसे सरल वर्कअराउंड प्रतीत होते हैं, इसलिए विधि को इस तरह से फिर से बनाया जा सकता है:
this.pages.forEach(page => page.draw(this.settings));
हालाँकि, विचार करें कि क्या कोड ने jQuery जैसी लाइब्रेरी का उपयोग किया है, जिसके तरीके thisविशेष रूप से बाँधते हैं । अब, इससे thisनिपटने के लिए दो मूल्य हैं :
Book.prototype.render = function () {
var book = this;
this.$pages.each(function (index) {
var $page = $(this);
book.draw(book.currentPage + index, $page);
});
};
हमें गतिशील रूप से बांधने के functionलिए उपयोग करना चाहिए । हम यहां एरो फंक्शन का उपयोग नहीं कर सकते।eachthis
कई thisमूल्यों से निपटना भी भ्रामक हो सकता है, क्योंकि यह जानना मुश्किल है कि thisएक लेखक किस बारे में बात कर रहा था:
function Reader() {
this.book.on('change', function () {
this.reformat();
});
}
क्या लेखक वास्तव में फोन करने का इरादा रखता था Book.prototype.reformat? या वह बांधना भूल गया this, और बुलाने का इरादा किया Reader.prototype.reformat? यदि हम हैंडलर को एरो फंक्शन में बदलते हैं, तो हम भी उसी तरह आश्चर्यचकित होंगे यदि लेखक डायनेमिक चाहता था this, फिर भी उसने एक एरो चुना क्योंकि यह एक लाइन में फिट होता है:
function Reader() {
this.book.on('change', () => this.reformat());
}
कोई भी ऐसा कर सकता है: "क्या यह असाधारण है कि तीर कभी-कभी गलत फ़ंक्शन का उपयोग कर सकता है? शायद अगर हमें केवल गतिशील thisमूल्यों की आवश्यकता होती है, तो अधिकांश समय तीर का उपयोग करना ठीक होगा।"
लेकिन अपने आप से यह पूछें: "क्या यह कोड को डिबग करने के लिए 'इसके लायक' होगा और यह पता लगाएगा कि त्रुटि का परिणाम एक 'किनारे के मामले' द्वारा लाया गया था?" "मैं ज्यादातर समय परेशानी से बचना पसंद करूंगा, लेकिन समय का 100%।
एक बेहतर तरीका है: हमेशा उपयोग करें function(ताकि thisहमेशा गतिशील रूप से बाध्य किया जा सके), और हमेशा thisएक चर के माध्यम से संदर्भ । विविधताएं शाब्दिक हैं और कई नामों को मानती हैं। thisएक चर को असाइन करने से आपके इरादे स्पष्ट हो जाएंगे:
function Reader() {
var reader = this;
reader.book.on('change', function () {
var book = this;
book.reformat();
reader.reformat();
});
}
इसके अलावा, हमेशाthis एक वेरिएबल को असाइन करना (तब भी जब thisकोई एकल या कोई अन्य कार्य नहीं होता है) यह सुनिश्चित करता है कि कोड बदलने के बाद भी किसी के इरादे स्पष्ट रहें।
इसके अलावा, गतिशील thisशायद ही असाधारण है। jQuery का उपयोग 50 मिलियन से अधिक वेबसाइटों पर किया जाता है (फरवरी 2016 में इस लेखन के रूप में)। यहाँ अन्य एपीआई thisगतिशील रूप से बाध्यकारी हैं :
- मोचा (~ 120k डाउनलोड कल) के माध्यम से अपने परीक्षणों के लिए तरीकों को उजागर करता है
this।
- ग्रंट (कल 63k डाउनलोड) के माध्यम से निर्माण कार्यों के लिए तरीकों को उजागर करता है
this।
- बैकबोन (~ 22k डाउनलोड कल) एक्सेस करने के तरीकों को परिभाषित करता है
this।
- ईवेंट API (जैसे DOM) एक के
EventTargetसाथ संदर्भित करता है this।
- प्रोटोटाइप एपीआई जो पैच या विस्तारित हैं, उदाहरण के साथ संदर्भित होते हैं
this।
( Http://trends.builtwith.com/javascript/jQuery और https://www.npmjs.com के माध्यम से आँकड़े ।)
आपको thisपहले से ही गतिशील बाइंडिंग की आवश्यकता है ।
एक शाब्दिक thisकभी-कभी अपेक्षित होती है, लेकिन कभी-कभी नहीं; जैसा कि एक गतिशील thisकभी-कभी अपेक्षित होता है, लेकिन कभी-कभी नहीं। शुक्र है, एक बेहतर तरीका है, जो हमेशा अपेक्षित बंधन का उत्पादन और संचार करता है।
ट्रिक सिंटैक्स के बारे में
एरो फ़ंक्शंस फ़ंक्शंस के लिए "छोटा वाक्य रचनात्मक रूप" प्रदान करने में सफल रहे। लेकिन क्या ये छोटे कार्य आपको अधिक सफल बनाएंगे?
क्या x => x * x"पढ़ने में आसान" है function (x) { return x * x; }? शायद यह है, क्योंकि यह कोड की एक एकल, छोटी लाइन का उत्पादन करने की अधिक संभावना है। डायसन के लिए पढ़ने की गति और स्क्रीन से पढ़ने की प्रभावशीलता पर लाइन की लंबाई का प्रभाव ,
एक मध्यम लाइन की लंबाई (प्रति पंक्ति 55 वर्ण) सामान्य और तेज गति से प्रभावी पढ़ने का समर्थन करने के लिए प्रकट होती है। इसने उच्चतम स्तर की समझ पैदा की। । ।
सशर्त (टर्नरी) ऑपरेटर के लिए और एकल-लाइन ifबयानों के लिए इसी तरह के औचित्य बनाए जाते हैं ।
हालाँकि, क्या आप वास्तव में प्रस्ताव में विज्ञापित सरल गणितीय कार्यों को लिख रहे हैं ? मेरे डोमेन गणितीय नहीं हैं, इसलिए मेरे सबरूटीन शायद ही कभी इतने सुंदर हैं। इसके बजाय, मैं आमतौर पर तीर के कार्यों को एक कॉलम की सीमा को तोड़ता हुआ देखता हूं, और संपादक या शैली गाइड के कारण दूसरी पंक्ति में लपेटता हूं, जो डायसन की परिभाषा से "पठनीयता" को कम करता है।
कोई यह कह सकता है कि, "जब संभव हो तो छोटे कार्यों के लिए लघु संस्करण का उपयोग कैसे करें?" लेकिन अब एक शैलीगत नियम एक भाषा की कमी का खंडन करता है: "कभी-कभी यह ध्यान में रखते हुए कि संभवत: केवल सबसे लंबे अंकन बांधेंगे, ध्यान में रखते हुए, सबसे कम फ़ंक्शन नोटेशन का उपयोग करने का प्रयास करें this।" इस तरह के टकराव से तीरों का दुरुपयोग होने का खतरा होता है।
तीर फ़ंक्शन सिंटैक्स के साथ कई समस्याएं हैं:
const a = x =>
doSomething(x);
const b = x =>
doSomething(x);
doSomethingElse(x);
ये दोनों कार्य वाक्यात्मक रूप से मान्य हैं। लेकिन doSomethingElse(x);शरीर में नहीं है b, यह सिर्फ एक खराब-इंडेंटेड, टॉप-लेवल स्टेटमेंट है।
ब्लॉक के रूप में विस्तार करते समय return, अब कोई निहित नहीं है , जिसे कोई भी बहाल करना भूल सकता है। लेकिन अभिव्यक्ति केवल एक साइड-इफ़ेक्ट उत्पन्न करने के उद्देश्य से की गई हो सकती है, इसलिए कौन जानता है कि एक स्पष्ट रूप returnसे आगे बढ़ना आवश्यक होगा?
const create = () => User.create();
const create = () => {
let user;
User.create().then(result => {
user = result;
return sendEmail();
}).then(() => user);
};
const create = () => {
let user;
return User.create().then(result => {
user = result;
return sendEmail();
}).then(() => user);
};
बाकी पैरामीटर के रूप में क्या किया जा सकता है, प्रसार ऑपरेटर के रूप में पार्स किया जा सकता है:
processData(data, ...results => {}) // Spread
processData(data, (...results) => {}) // Rest
असाइनमेंट को डिफ़ॉल्ट तर्कों के साथ भ्रमित किया जा सकता है:
const a = 1;
let x;
const b = x => {}; // No default
const b = x = a => {}; // "Adding a default" instead creates a double assignment
const b = (x = a) => {}; // Remember to add parens
ब्लॉक वस्तुओं की तरह दिखते हैं:
(id) => id // Returns `id`
(id) => {name: id} // Returns `undefined` (it's a labeled statement)
(id) => ({name: id}) // Returns an object
इसका क्या मतलब है?
() => {}
क्या लेखक एक खाली ऑप्शन या एक ऐसा फ़ंक्शन बनाने का इरादा रखता है, जो एक खाली वस्तु लौटाता है? (इसे ध्यान में रखते, हम कभी भी इस प्रकार रखना चाहिए {के बाद =>? चाहिए हम अपने आप को केवल अभिव्यक्ति वाक्य रचना के लिए प्रतिबंधित? यही कारण है कि आगे तीर 'आवृत्ति कम होगी।)
=>जैसा दिखता है <=और >=:
x => 1 ? 2 : 3
x <= 1 ? 2 : 3
if (x => 1) {}
if (x >= 1) {}
एक तीर फ़ंक्शन अभिव्यक्ति को तुरंत लागू करने के लिए, एक को ()बाहर की तरफ रखना होगा , फिर ()भी अंदर की तरफ रखना वैध है और जानबूझकर हो सकता है।
(() => doSomething()()) // Creates function calling value of `doSomething()`
(() => doSomething())() // Calls the arrow function
हालांकि, अगर (() => doSomething()());कोई तुरंत-लागू फ़ंक्शन अभिव्यक्ति लिखने के इरादे से लिखता है, तो बस कुछ नहीं होगा।
यह तर्क देना कठिन है कि तीर के कार्य उपरोक्त सभी मामलों को ध्यान में रखते हुए "अधिक समझने योग्य" हैं। कोई भी इस वाक्यविन्यास का उपयोग करने के लिए आवश्यक सभी विशेष नियमों को सीख सकता है । यह वास्तव में इसके लायक है?
वाक्यविन्यास functionअनैच्छिक रूप से सामान्यीकृत है। functionविशेष रूप से उपयोग करने के लिए भाषा स्वयं को भ्रमित कोड लिखने से रोकती है। उन प्रक्रियाओं को लिखने के लिए जिन्हें सभी मामलों में वाक्यविन्यास समझा जाना चाहिए, मैं चुनता हूं function।
एक दिशानिर्देश के बारे में
आप एक दिशानिर्देश का अनुरोध करते हैं जिसे "स्पष्ट" और "सुसंगत" होना चाहिए। एरो फ़ंक्शंस का उपयोग करने के परिणामस्वरूप अंतिम रूप से वाक्य-रचना, तार्किक रूप से अमान्य कोड, दोनों फ़ंक्शन रूपों के साथ intertwined, सार्थक और मनमाने ढंग से हो जाएंगे। इसलिए, मैं निम्नलिखित प्रदान करता हूं:
ES6 में फ़ंक्शन सूचना के लिए दिशानिर्देश:
- हमेशा प्रक्रियाओं के साथ बनाएँ
function।
- हमेशा
thisएक चर के लिए असाइन करें। उपयोग न करें () => {}।
Fixed this bound to scope at initialisationएक सीमा के रूप में मानते हैं?