मैंने हाल ही में किसी और के जावास्क्रिप्ट कोड को बनाए रखना शुरू किया है। मैं बग को ठीक कर रहा हूं, सुविधाओं को जोड़ रहा हूं और कोड को साफ करने और इसे और अधिक सुसंगत बनाने की कोशिश कर रहा हूं।
पिछले डेवलपर ने फ़ंक्शंस घोषित करने के दो तरीकों का इस्तेमाल किया और इसके पीछे कोई कारण है या नहीं, तो मैं काम नहीं कर सकता।
दो तरीके हैं:
var functionOne = function() {
// Some code
};
function functionTwo() {
// Some code
}
इन दो अलग-अलग तरीकों का उपयोग करने के क्या कारण हैं और प्रत्येक के पक्ष और विपक्ष क्या हैं? क्या ऐसा कुछ है जो एक विधि से किया जा सकता है जो दूसरे के साथ नहीं किया जा सकता है?
25 जवाब
अंतर यह है कि functionOne
एक फंक्शन एक्सप्रेशन है और इसलिए केवल तभी परिभाषित किया जाता है जब वह लाइन पहुंच जाती है, जबकि functionTwo
एक फंक्शन डिक्लेरेशन है और जैसे ही इसके आसपास के फंक्शन या स्क्रिप्ट को निष्पादित किया जाता है, इसे परिभाषित किया जाता है। a href="http://adripofjavascript.com/blog/drips/variable-and-function-hoisting.html" rel="noreferrer">होस्टिंग)।
उदाहरण के लिए, एक फ़ंक्शन अभिव्यक्ति:
// TypeError: functionOne is not a function
functionOne();
var functionOne = function() {
console.log("Hello!");
};
और, एक समारोह घोषणा:
// Outputs: "Hello!"
functionTwo();
function functionTwo() {
console.log("Hello!");
}
ऐतिहासिक रूप से, ब्लॉक के भीतर परिभाषित फ़ंक्शन घोषणाओं को ब्राउज़रों के बीच असंगत रूप से नियंत्रित किया गया था। सख्त मोड (ES5 में पेश किया गया) ने फ़ंक्शन घोषणाओं को उनके संलग्न ब्लॉक में स्कोप करके इसे हल किया।
'use strict';
{ // note this block!
function functionThree() {
console.log("Hello!");
}
}
functionThree(); // ReferenceError
फ़ंक्शन बनाने वाले मानक रूपों के बारे में यहां बताया गया है: (मूल रूप से किसी अन्य प्रश्न के लिए लिखा गया है, लेकिन विहित प्रश्न में स्थानांतरित होने के बाद अनुकूलित किया गया है।)
शर्तें:
- ES5: ECMAScript 5वां संस्करण, 2009
- ES2015: ECMAScript 2015 (भी "ES6" के रूप में जाना जाता है)
त्वरित सूची:
समारोह घोषणा
"गुमनाम"
function
अभिव्यक्ति (जो शब्द के बावजूद, कभी-कभी नामों के साथ फ़ंक्शन बनाता है)नामित
function
एक्सप्रेशनएक्सेसर फंक्शन इनिशियलाइज़र (ES5+)
एरो फंक्शन एक्सप्रेशन (ES2015+) (जो, अनाम फ़ंक्शन एक्सप्रेशन की तरह, एक स्पष्ट नाम शामिल नहीं करता है, और फिर भी नामों के साथ फ़ंक्शन बना सकता है)
वस्तु प्रारंभकर्ता में विधि घोषणा (ES2015+)
class
(ES2015+) में कंस्ट्रक्टर और मेथड डिक्लेरेशन
समारोह घोषणा
पहला फॉर्म एक फंक्शन डिक्लेरेशन है, जो इस तरह दिखता है:
function x() {
console.log('x');
}
एक फ़ंक्शन घोषणा एक घोषणा है; यह एक बयान या अभिव्यक्ति नहीं है। जैसे, आप इसका पालन ;
के साथ नहीं करते (हालाँकि ऐसा करना हानिरहित है)।
किसी भी चरण-दर-चरण कोड को निष्पादित करने से पहले जब निष्पादन उस संदर्भ में प्रवेश करता है जिसमें यह प्रकट होता है, तो एक फ़ंक्शन घोषणा संसाधित की जाती है। यह जो फ़ंक्शन बनाता है उसे एक उचित नाम दिया गया है (x
ऊपर के उदाहरण में), और उस नाम को उस दायरे में रखा गया है जिसमें घोषणा दिखाई देती है।
चूंकि इसे उसी संदर्भ में किसी भी चरण-दर-चरण कोड से पहले संसाधित किया जाता है, आप इस तरह की चीजें कर सकते हैं:
x(); // Works even though it's above the declaration
function x() {
console.log('x');
}
ES2015 तक, यदि आप एक नियंत्रण संरचना जैसे try
, if
, switch
, while
, आदि, इस तरह:
if (someCondition) {
function foo() { // <===== HERE THERE
} // <===== BE DRAGONS
}
और चूंकि उन्हें चरण-दर-चरण कोड चलाने से पहले संसाधित किया जाता है, इसलिए यह जानना मुश्किल है कि जब वे नियंत्रण संरचना में हों तो उन्हें क्या करना चाहिए।
हालांकि ऐसा करना ES2015 तक निर्दिष्ट नहीं था, यह ब्लॉकों में फ़ंक्शन घोषणाओं का समर्थन करने के लिए एक स्वीकार्य एक्सटेंशन था। दुर्भाग्य से (और अनिवार्य रूप से), विभिन्न इंजनों ने अलग-अलग चीजें कीं।
ES2015 के अनुसार, विनिर्देश कहता है कि क्या करना है। वास्तव में, यह करने के लिए तीन अलग-अलग चीजें देता है:
- यदि वेब ब्राउज़र पर लूज़ मोड नहीं में है, तो JavaScript इंजन को एक काम करना चाहिए
- यदि वेब ब्राउज़र पर ढीले मोड में, जावास्क्रिप्ट इंजन को कुछ और करना चाहिए
- यदि सख्त मोड (ब्राउज़र या नहीं) में है, तो जावास्क्रिप्ट इंजन को एक और काम करना चाहिए
ढीले मोड के नियम मुश्किल हैं, लेकिन सख्त मोड में, ब्लॉक में फ़ंक्शन घोषणाएं आसान हैं: वे ब्लॉक के लिए स्थानीय हैं (उनके पास ब्लॉक स्कोप है, जो है ES2015 में भी नया), और वे ब्लॉक के शीर्ष पर फहराए गए हैं। इसलिए:
"use strict";
if (someCondition) {
foo(); // Works just fine
function foo() {
}
}
console.log(typeof foo); // "undefined" (`foo` is not in scope here
// because it's not in the same block)
"गुमनाम" function
अभिव्यक्ति
दूसरे सामान्य रूप को अनाम फ़ंक्शन एक्सप्रेशन कहा जाता है:
var y = function () {
console.log('y');
};
सभी अभिव्यक्तियों की तरह, कोड के चरण-दर-चरण निष्पादन में पहुंचने पर इसका मूल्यांकन किया जाता है।
ES5 में, यह जो फ़ंक्शन बनाता है उसका कोई नाम नहीं है (यह अनाम है)। ES2015 में, फ़ंक्शन को संदर्भ से संदर्भित करके यदि संभव हो तो एक नाम दिया गया है। ऊपर के उदाहरण में, नाम y
होगा। कुछ ऐसा ही किया जाता है जब फ़ंक्शन किसी प्रॉपर्टी इनिशियलाइज़र का मान होता है। (ऐसा कब होता है और नियमों के विवरण के लिए, विनिर्देश में SetFunctionName
खोजें — यह सभी जगह दिखाई देता है।)
नामित function
एक्सप्रेशन
तीसरा रूप एक नामांकित फ़ंक्शन एक्सप्रेशन ("एनएफई") है:
var z = function w() {
console.log('zw')
};
यह जो फ़ंक्शन बनाता है उसका एक उचित नाम होता है (w
इस मामले में)। सभी अभिव्यक्तियों की तरह, इसका मूल्यांकन तब किया जाता है जब यह कोड के चरण-दर-चरण निष्पादन में पहुंच जाता है। फ़ंक्शन का नाम उस दायरे में जोड़ा गया नहीं है जिसमें व्यंजक प्रकट होता है; नाम है फ़ंक्शन के दायरे में ही:
var z = function w() {
console.log(typeof w); // "function"
};
console.log(typeof w); // "undefined"
ध्यान दें कि एनएफई अक्सर जावास्क्रिप्ट कार्यान्वयन के लिए बग का स्रोत रहा है। IE8 और इससे पहले, उदाहरण के लिए, NFE को पूरी तरह से गलत तरीके से हैंडल करते हैं, जिससे दो अलग-अलग दो अलग-अलग समय पर कार्य करता है। सफारी के शुरुआती संस्करणों में भी समस्याएँ थीं। अच्छी खबर यह है कि ब्राउज़र के वर्तमान संस्करणों (आईई 9 और ऊपर, वर्तमान सफारी) में अब वे मुद्दे नहीं हैं। (लेकिन इस लेखन के रूप में, दुख की बात है कि IE8 व्यापक रूप से उपयोग में है, और इसलिए सामान्य रूप से वेब के लिए कोड के साथ NFE का उपयोग करना अभी भी समस्याग्रस्त है।)
एक्सेसर फंक्शन इनिशियलाइज़र (ES5+)
कभी-कभी कार्य बड़े पैमाने पर किसी का ध्यान नहीं जा सकता है; एक्सेसर फ़ंक्शंस के मामले में ऐसा ही है। यहाँ एक उदाहरण है:
var obj = {
value: 0,
get f() {
return this.value;
},
set f(v) {
this.value = v;
}
};
console.log(obj.f); // 0
console.log(typeof obj.f); // "number"
ध्यान दें कि जब मैंने फ़ंक्शन का उपयोग किया था, तो मैंने ()
! ऐसा इसलिए है क्योंकि यह किसी प्रॉपर्टी के लिए एक्सेसर फ़ंक्शन है। हम संपत्ति को सामान्य तरीके से प्राप्त करते हैं और सेट करते हैं, लेकिन पर्दे के पीछे, फ़ंक्शन को कहा जाता है।
आप Object.defineProperty
, Object.defineProperties
, और Object.create
के कम ज्ञात दूसरे तर्क के साथ एक्सेसर फ़ंक्शन भी बना सकते हैं।
एरो फंक्शन एक्सप्रेशन (ES2015+)
ES2015 हमारे लिए एरो फंक्शन लेकर आया है। यहाँ एक उदाहरण है:
var a = [1, 2, 3];
var b = a.map(n => n * 2);
console.log(b.join(", ")); // 2, 4, 6
देखें कि n => n * 2
बात map()
कॉल में छिपी है? वह एक समारोह है।
तीर कार्यों के बारे में कुछ बातें:
उनका अपना
this
नहीं है। इसके बजाय, वे उस संदर्भ केthis
को बंद करते हैं जहां उन्हें परिभाषित किया गया है। (वेarguments
और, जहां प्रासंगिक हो,super
को भी बंद कर देते हैं।) इसका मतलब यह है कि उनके भीतरthis
वही है जहां वे बनाए गए हैंthis
, और बदला नहीं जा सकता।जैसा कि आपने उपरोक्त के साथ देखा होगा, आप कीवर्ड
function
का उपयोग नहीं करते हैं; इसके बजाय, आप=>
का उपयोग करते हैं।
ऊपर दिया गया n => n * 2
उदाहरण उन्हीं का एक रूप है। यदि आपके पास फ़ंक्शन पास करने के लिए कई तर्क हैं, तो आप माता-पिता का उपयोग करते हैं:
var a = [1, 2, 3];
var b = a.map((n, i) => n * i);
console.log(b.join(", ")); // 0, 2, 6
(याद रखें कि Array#map
प्रविष्टि को पहले तर्क के रूप में और सूचकांक को दूसरे के रूप में पास करता है।)
दोनों ही मामलों में, फ़ंक्शन का मुख्य भाग केवल एक अभिव्यक्ति है; फ़ंक्शन का वापसी मान स्वचालित रूप से उस अभिव्यक्ति का परिणाम होगा (आप एक स्पष्ट return
का उपयोग नहीं करते हैं)।
यदि आप केवल एक अभिव्यक्ति से अधिक कर रहे हैं, तो सामान्य रूप से {}
और एक स्पष्ट return
(यदि आपको कोई मान वापस करने की आवश्यकता है) का उपयोग करें:
var a = [
{first: "Joe", last: "Bloggs"},
{first: "Albert", last: "Bloggs"},
{first: "Mary", last: "Albright"}
];
a = a.sort((a, b) => {
var rv = a.last.localeCompare(b.last);
if (rv === 0) {
rv = a.first.localeCompare(b.first);
}
return rv;
});
console.log(JSON.stringify(a));
{ ... }
के बिना संस्करण को एक्सप्रेशन बॉडी या संक्षिप्त बॉडी के साथ एरो फंक्शन कहा जाता है। (इसके अलावा: एक संक्षिप्त तीर फ़ंक्शन।) { ... }
बॉडी को परिभाषित करने वाला एक फ़ंक्शन बॉडी वाला एक एरो फ़ंक्शन है। (साथ ही: एक वर्बोज़ तीर फ़ंक्शन।)
वस्तु प्रारंभकर्ता में विधि घोषणा (ES2015+)
ES2015 एक संपत्ति घोषित करने के एक छोटे रूप की अनुमति देता है जो एक फ़ंक्शन को संदर्भित करता है जिसे विधि परिभाषा कहा जाता है; यह इस तरह दिख रहा है:
var o = {
foo() {
}
};
ES5 और इससे पहले के लगभग समकक्ष होंगे:
var o = {
foo: function foo() {
}
};
अंतर (वर्बोसिटी के अलावा) यह है कि एक विधि super
का उपयोग कर सकती है, लेकिन एक फ़ंक्शन नहीं कर सकता। तो उदाहरण के लिए, यदि आपके पास एक ऑब्जेक्ट था जो विधि वाक्यविन्यास का उपयोग करके परिभाषित (कहें) valueOf
, यह super.valueOf()
का उपयोग कर सकता है मान प्राप्त करने के लिए Object.prototype.valueOf
वापस आ गया होता (संभवतः कुछ और करने से पहले) it), जबकि ES5 संस्करण को इसके बजाय Object.prototype.valueOf.call(this)
करना होगा।
इसका मतलब यह भी है कि विधि में उस वस्तु का संदर्भ है जिस पर इसे परिभाषित किया गया था, इसलिए यदि वह वस्तु अस्थायी है (उदाहरण के लिए, आप इसे Object.assign
में स्रोत वस्तुओं में से एक के रूप में पास कर रहे हैं), विधि वाक्यविन्यास सकता है का अर्थ है कि वस्तु को स्मृति में तब रखा जाता है जब अन्यथा इसे कचरा एकत्र किया जा सकता था (यदि जावास्क्रिप्ट इंजन उस स्थिति का पता नहीं लगाता है और यदि कोई भी विधि super
का उपयोग नहीं करती है तो इसे संभालती है)।
class
(ES2015+) में कंस्ट्रक्टर और मेथड डिक्लेरेशन
ES2015 हमें class
सिंटैक्स लाता है, जिसमें घोषित कंस्ट्रक्टर और तरीके शामिल हैं:
class Person {
constructor(firstName, lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
getFullName() {
return this.firstName + " " + this.lastName;
}
}
ऊपर दो फ़ंक्शन घोषणाएं हैं: एक कंस्ट्रक्टर के लिए, जिसे Person
नाम मिलता है, और एक getFullName
के लिए, जो कि Person.prototype
को असाइन किया गया फ़ंक्शन है।
आपके द्वारा वहां पोस्ट किए गए दो कोड स्निपेट लगभग सभी उद्देश्यों के लिए समान व्यवहार करेंगे।
हालांकि, व्यवहार में अंतर यह है कि पहले संस्करण (var functionOne = function() {}
) के साथ, उस फ़ंक्शन को कोड में उस बिंदु के बाद ही कॉल किया जा सकता है।
दूसरे संस्करण (function functionTwo()
) के साथ, फ़ंक्शन उस कोड के लिए उपलब्ध है जो ऊपर चलता है जहां फ़ंक्शन घोषित किया गया है।
ऐसा इसलिए है क्योंकि पहले संस्करण के साथ, फ़ंक्शन रन टाइम पर वेरिएबल foo
को असाइन किया जाता है। दूसरे में, फ़ंक्शन उस पहचानकर्ता को सौंपा जाता है, foo
, पार्स समय पर।
अधिक तकनीकी जानकारी
जावास्क्रिप्ट में कार्यों को परिभाषित करने के तीन तरीके हैं।
- आपका पहला स्निपेट एक फ़ंक्शन एक्सप्रेशन दिखाता है। इसमें फ़ंक्शन बनाने के लिए "फ़ंक्शन" ऑपरेटर का उपयोग करना शामिल है - उस ऑपरेटर का परिणाम किसी भी चर या ऑब्जेक्ट प्रॉपर्टी में संग्रहीत किया जा सकता है। इस तरह से फंक्शन एक्सप्रेशन शक्तिशाली है। फ़ंक्शन एक्सप्रेशन को अक्सर "अनाम फ़ंक्शन" कहा जाता है, क्योंकि इसका कोई नाम नहीं होता है,
- आपका दूसरा उदाहरण एक कार्य घोषणा है। यह फ़ंक्शन बनाने के लिए "फ़ंक्शन" कथन का उपयोग करता है। फ़ंक्शन को पार्स समय पर उपलब्ध कराया जाता है और उस दायरे में कहीं भी कहा जा सकता है। आप इसे बाद में भी एक वेरिएबल या ऑब्जेक्ट प्रॉपर्टी में स्टोर कर सकते हैं।
- किसी फ़ंक्शन को परिभाषित करने का तीसरा तरीका "Function ()" कंस्ट्रक्टर है, जो आपके मूल पोस्ट में नहीं दिखाया गया है। इसका उपयोग करने की अनुशंसा नहीं की जाती है क्योंकि यह
eval()
की तरह ही काम करता है, जिसमें इसकी समस्याएं हैं।
अन्य टिप्पणीकारों ने पहले ही उपरोक्त दो रूपों के अर्थ अंतर को कवर कर लिया है। मैं एक शैलीगत अंतर नोट करना चाहता था: केवल "असाइनमेंट" भिन्नता किसी अन्य वस्तु की संपत्ति सेट कर सकती है।
मैं अक्सर इस तरह के पैटर्न के साथ जावास्क्रिप्ट मॉड्यूल बनाता हूं:
(function(){
var exports = {};
function privateUtil() {
...
}
exports.publicUtil = function() {
...
};
return exports;
})();
इस पैटर्न के साथ, आपके सार्वजनिक कार्य सभी असाइनमेंट का उपयोग करेंगे, जबकि आपके निजी कार्य घोषणा का उपयोग करेंगे।
(यह भी ध्यान दें कि असाइनमेंट को कथन के बाद अर्धविराम की आवश्यकता होनी चाहिए, जबकि घोषणा इसे प्रतिबंधित करती है।)
जब आपको किसी फ़ंक्शन की पिछली परिभाषाओं को ओवरराइड करने से बचने की आवश्यकता होती है, तो दूसरे के लिए पहली विधि को कब प्राथमिकता दी जाए, इसका एक उदाहरण है।
साथ में
if (condition){
function myfunction(){
// Some code
}
}
, myfunction
की यह परिभाषा किसी भी पिछली परिभाषा को ओवरराइड कर देगी, क्योंकि यह पार्स-टाइम पर की जाएगी।
जबकि
if (condition){
var myfunction = function (){
// Some code
}
}
myfunction
को परिभाषित करने का सही काम तभी करता है जब condition
मिले हों।
एक महत्वपूर्ण कारण आपके नाम स्थान के "रूट" के रूप में एक और केवल एक चर जोड़ना है...
var MyNamespace = {}
MyNamespace.foo= function() {
}
या
var MyNamespace = {
foo: function() {
},
...
}
नेमस्पेसिंग के लिए कई तकनीकें हैं। उपलब्ध जावास्क्रिप्ट मॉड्यूल के ढेर के साथ यह और अधिक महत्वपूर्ण हो गया है।
यह भी देखें मैं जावास्क्रिप्ट में नेमस्पेस कैसे घोषित करूं?
मैं अपना उत्तर सिर्फ इसलिए जोड़ रहा हूं क्योंकि बाकी सभी ने उत्थापन भाग को अच्छी तरह से कवर कर लिया है।
मैं काफी समय से इस बारे में सोच रहा था कि कौन सा तरीका बेहतर है, और अब मैं http://jsperf.com को धन्यवाद देता हूं। जानना :)
कार्य घोषणाएं तेज़ हैं, और यही वास्तव में वेब देव में मायने रखता है, है ना? ;)
एक फ़ंक्शन डिक्लेरेशन और एक वेरिएबल को असाइन किया गया एक फंक्शन एक्सप्रेशन एक बार बाइंडिंग स्थापित होने के बाद समान व्यवहार करता है।
हालांकि, कैसे और कब में फ़ंक्शन ऑब्जेक्ट वास्तव में इसके वेरिएबल के साथ जुड़ा होता है, इसमें अंतर होता है। यह अंतर JavaScript में चर उत्थापन नामक तंत्र के कारण है।
मूल रूप से, सभी फ़ंक्शन घोषणाएं और परिवर्तनीय घोषणाएं फ़ंक्शन के शीर्ष पर फहराई जाती हैं जिसमें घोषणा होती है (इसीलिए हम कहते हैं कि जावास्क्रिप्ट में फ़ंक्शन स्कोप है)।
जब कोई फ़ंक्शन घोषणा फहराया जाता है, तो फ़ंक्शन बॉडी "निम्नानुसार" इसलिए जब फ़ंक्शन बॉडी का मूल्यांकन किया जाता है, तो वेरिएबल तुरंत होगा किसी फ़ंक्शन ऑब्जेक्ट के लिए बाध्य होना।
जब एक वैरिएबल डिक्लेरेशन फहराया जाता है, तो इनिशियलाइज़ेशन नहीं करता है का पालन करें, लेकिन "पीछे छोड़ दिया" है। वेरिएबल को इनिशियलाइज़ किया गया है
undefined
फंक्शन बॉडी की शुरुआत में, और असाइन किया जाएगा कोड में अपने मूल स्थान पर एक मान। (वास्तव में, इसे हर स्थान पर एक मान दिया जाएगा जहां समान नाम वाले चर की घोषणा होती है।)
उत्थापन का क्रम भी महत्वपूर्ण है: फ़ंक्शन घोषणाएं समान नाम के साथ चर घोषणाओं पर पूर्वता लेती हैं, और अंतिम फ़ंक्शन घोषणा समान नाम के साथ पिछले फ़ंक्शन घोषणाओं पर पूर्वता लेती है।
कुछ उदाहरण...
var foo = 1;
function bar() {
if (!foo) {
var foo = 10 }
return foo; }
bar() // 10
वेरिएबल foo
को फ़ंक्शन के शीर्ष पर फहराया जाता है, undefined
से आरंभ किया जाता है, ताकि !foo
true
हो, इसलिए foo
को 10
असाइन किया गया है। . foo
, bar
के दायरे से बाहर कोई भूमिका नहीं निभाता है और अछूता है।
function f() {
return a;
function a() {return 1};
var a = 4;
function a() {return 2}}
f()() // 2
function f() {
return a;
var a = 4;
function a() {return 1};
function a() {return 2}}
f()() // 2
फ़ंक्शन घोषणाएं परिवर्तनीय घोषणाओं पर पूर्वता लेती हैं, और अंतिम फ़ंक्शन घोषणा "छड़ी" होती है।
function f() {
var a = 4;
function a() {return 1};
function a() {return 2};
return a; }
f() // 4
इस उदाहरण में a
को दूसरे फंक्शन डिक्लेरेशन के मूल्यांकन के परिणामस्वरूप फंक्शन ऑब्जेक्ट के साथ इनिशियलाइज़ किया जाता है, और फिर इसे 4
असाइन किया जाता है।
var a = 1;
function b() {
a = 10;
return;
function a() {}}
b();
a // 1
यहां फंक्शन डिक्लेरेशन को पहले फहराया जाता है, वेरिएबल a
को डिक्लेयर और इनिशियलाइज़ किया जाता है। इसके बाद, यह वेरिएबल 10
असाइन किया गया है। दूसरे शब्दों में: असाइनमेंट बाहरी चर a
को असाइन नहीं करता है।
पहला उदाहरण एक फ़ंक्शन घोषणा है:
function abc(){}
दूसरा उदाहरण एक फ़ंक्शन अभिव्यक्ति है:
var abc = function() {};
मुख्य अंतर यह है कि उन्हें कैसे फहराया जाता है (उठाया और घोषित किया जाता है)। पहले उदाहरण में, संपूर्ण फ़ंक्शन घोषणा को फहराया जाता है। दूसरे उदाहरण में केवल var 'abc' फहराया जाता है, इसका मान (फ़ंक्शन) अपरिभाषित होगा, और फ़ंक्शन स्वयं घोषित स्थिति में रहता है।
सीधे शब्दों में:
//this will work
abc(param);
function abc(){}
//this would fail
abc(param);
var abc = function() {}
इस विषय के बारे में और अधिक अध्ययन करने के लिए मैं आपको इसकी पुरजोर अनुशंसा करता हूं लिंक
कोड रखरखाव लागत के संदर्भ में, नामित कार्य अधिक बेहतर हैं:
- उस स्थान से स्वतंत्र जहां उन्हें घोषित किया गया है (लेकिन अभी भी दायरे से सीमित है)।
- सशर्त आरंभीकरण जैसी गलतियों के लिए अधिक प्रतिरोधी (यदि आप चाहें तो अभी भी ओवरराइड करने में सक्षम हैं)।
- स्कोप कार्यक्षमता के अलग-अलग स्थानीय कार्यों को आवंटित करके कोड अधिक पठनीय हो जाता है। आमतौर पर दायरे में कार्यक्षमता पहले जाती है, उसके बाद स्थानीय कार्यों की घोषणा होती है।
- डीबगर में आप "अनाम/मूल्यांकन" फ़ंक्शन के बजाय कॉल स्टैक पर फ़ंक्शन का नाम स्पष्ट रूप से देखेंगे।
मुझे संदेह है कि नामित कार्यों के लिए और अधिक PROS का पालन किया जाता है। और नामित कार्यों के लाभ के रूप में सूचीबद्ध अज्ञात लोगों के लिए नुकसान है।
ऐतिहासिक रूप से, अनाम फ़ंक्शन नामित फ़ंक्शन वाले सदस्यों को सूचीबद्ध करने के लिए एक भाषा के रूप में जावास्क्रिप्ट की अक्षमता से प्रकट हुए:
{
member:function() { /* How do I make "this.member" a named function? */
}
}
कंप्यूटर विज्ञान के संदर्भ में, हम गुमनाम कार्यों और नामित कार्यों के बारे में बात करते हैं। मुझे लगता है कि सबसे महत्वपूर्ण अंतर यह है कि एक अज्ञात फ़ंक्शन किसी नाम से बाध्य नहीं है, इसलिए नाम अज्ञात फ़ंक्शन है। जावास्क्रिप्ट में यह एक प्रथम श्रेणी की वस्तु है जिसे गतिशील रूप से रनटाइम पर घोषित किया जाता है।
अनाम फ़ंक्शन और लैम्ब्डा कैलकुलस के बारे में अधिक जानकारी के लिए, विकिपीडिया एक अच्छी शुरुआत है: Anonymous Functions।
मैं अपने कोड में एक बहुत विशिष्ट कारण के लिए परिवर्तनीय दृष्टिकोण का उपयोग करता हूं, जिसका सिद्धांत ऊपर एक सार तरीके से कवर किया गया है, लेकिन एक उदाहरण सीमित जावास्क्रिप्ट विशेषज्ञता के साथ मेरे जैसे कुछ लोगों की मदद कर सकता है।
मेरे पास कोड है जिसे मुझे 160 स्वतंत्र रूप से डिज़ाइन किए गए ब्रांडिंग के साथ चलाने की आवश्यकता है। अधिकांश कोड साझा फ़ाइलों में है, लेकिन ब्रांडिंग-विशिष्ट सामग्री एक अलग फ़ाइल में है, प्रत्येक ब्रांडिंग के लिए एक।
कुछ ब्रांडिंग के लिए विशिष्ट कार्यों की आवश्यकता होती है, और कुछ के लिए नहीं। कभी-कभी मुझे नई ब्रांडिंग-विशिष्ट चीजें करने के लिए नए फ़ंक्शन जोड़ने पड़ते हैं। मुझे साझा कोड को बदलने में खुशी हो रही है, लेकिन मैं ब्रांडिंग फ़ाइलों के सभी 160 सेटों को बदलना नहीं चाहता।
वेरिएबल सिंटैक्स का उपयोग करके, मैं साझा कोड में वेरिएबल (एक फ़ंक्शन पॉइंटर अनिवार्य रूप से) घोषित कर सकता हूं और या तो एक छोटा स्टब फ़ंक्शन असाइन कर सकता हूं, या शून्य पर सेट कर सकता हूं।
एक या दो ब्रांडिंग जिन्हें फ़ंक्शन के विशिष्ट कार्यान्वयन की आवश्यकता होती है, वे फ़ंक्शन के अपने संस्करण को परिभाषित कर सकते हैं और यदि वे चाहें तो इसे वेरिएबल को असाइन कर सकते हैं, और बाकी कुछ भी नहीं करते हैं। साझा कोड में इसे निष्पादित करने से पहले मैं एक शून्य फ़ंक्शन के लिए परीक्षण कर सकता हूं।
उपरोक्त लोगों की टिप्पणियों से, मैं इकट्ठा करता हूं कि एक स्थिर कार्य को भी फिर से परिभाषित करना संभव हो सकता है, लेकिन मुझे लगता है कि परिवर्तनीय समाधान अच्छा और स्पष्ट है।
ग्रेग का उत्तर काफी अच्छा है, लेकिन मैं अब भी इसमें कुछ जोड़ना चाहूंगा जो मैंने अभी-अभी डगलस क्रॉकफोर्ड के वीडियो।
फ़ंक्शन एक्सप्रेशन:
var foo = function foo() {};
कार्य विवरण:
function foo() {};
फंक्शन स्टेटमेंट var
स्टेटमेंट के लिए function
वैल्यू के साथ सिर्फ एक शॉर्टहैंड है।
इसलिए
function foo() {};
तक फैलता है
var foo = function foo() {};
जो आगे विस्तार करता है:
var foo = undefined;
foo = function foo() {};
और वे दोनों कोड के शीर्ष पर फहराए जाते हैं।
@EugeneLazutkin एक उदाहरण देता है जहां वह एक असाइन किए गए फ़ंक्शन को नाम देता है जो shortcut()
को स्वयं के आंतरिक संदर्भ के रूप में उपयोग करने में सक्षम हो। जॉन रेसिग एक और उदाहरण देता है - किसी अन्य ऑब्जेक्ट को असाइन किए गए पुनरावर्ती फ़ंक्शन की प्रतिलिपि बनाना अपने उन्नत जावास्क्रिप्ट सीखना ट्यूटोरियल। गुणों के लिए फ़ंक्शन असाइन करना यहां सख्ती से सवाल नहीं है, मैं सक्रिय रूप से ट्यूटोरियल को आज़माने की सलाह देता हूं - ऊपरी दाएं कोने में बटन पर क्लिक करके कोड चलाएं, और अपनी पसंद के अनुसार संपादित करने के लिए कोड पर डबल क्लिक करें।
ट्यूटोरियल के उदाहरण: yell()
में पुनरावर्ती कॉल:
जब मूल निंजा ऑब्जेक्ट को हटा दिया जाता है तो परीक्षण विफल हो जाते हैं। (पेज 13)
var ninja = {
yell: function(n){
return n > 0 ? ninja.yell(n-1) + "a" : "hiy";
}
};
assert( ninja.yell(4) == "hiyaaaa", "A single object isn't too bad, either." );
var samurai = { yell: ninja.yell };
var ninja = null;
try {
samurai.yell(4);
} catch(e){
assert( false, "Uh, this isn't good! Where'd ninja.yell go?" );
}
यदि आप उस फ़ंक्शन का नाम देते हैं जिसे रिकर्सिवली कॉल किया जाएगा, तो परीक्षण पास हो जाएंगे। (पेज 14 )
var ninja = {
yell: function yell(n){
return n > 0 ? yell(n-1) + "a" : "hiy";
}
};
assert( ninja.yell(4) == "hiyaaaa", "Works as we would expect it to!" );
var samurai = { yell: ninja.yell };
var ninja = {};
assert( samurai.yell(4) == "hiyaaaa", "The method correctly calls itself." );
।
- समारोह की उपलब्धता (दायरा)
निम्नलिखित कार्य करता है क्योंकि function add()
निकटतम ब्लॉक के दायरे में है:
try {
console.log("Success: ", add(1, 1));
} catch(e) {
console.log("ERROR: " + e);
}
function add(a, b){
return a + b;
}
निम्नलिखित काम नहीं करता है क्योंकि चर add
को फ़ंक्शन मान असाइन किए जाने से पहले चर को कॉल किया जाता है।
try {
console.log("Success: ", add(1, 1));
} catch(e) {
console.log("ERROR: " + e);
}
var add=function(a, b){
return a + b;
}
उपरोक्त कोड नीचे दिए गए कोड की कार्यक्षमता के समान है। ध्यान दें कि स्पष्ट रूप से add = undefined
निर्दिष्ट करना अतिश्योक्तिपूर्ण है क्योंकि केवल var add;
करना var add=undefined
जैसा ही है।
var add = undefined;
try {
console.log("Success: ", add(1, 1));
} catch(e) {
console.log("ERROR: " + e);
}
add = function(a, b){
return a + b;
}
निम्नलिखित काम नहीं करता क्योंकि var add=
एक व्यंजक शुरू करता है और निम्नलिखित function add()
को ब्लॉक के बजाय एक व्यंजक बनाता है। नामांकित कार्य केवल स्वयं और उनके आस-पास के ब्लॉक के लिए दृश्यमान हैं। चूंकि function add()
यहां एक व्यंजक है, इसका कोई आसपास का खंड नहीं है, इसलिए यह केवल स्वयं के लिए दृश्यमान है।
try {
console.log("Success: ", add(1, 1));
} catch(e) {
console.log("ERROR: " + e);
}
var add=function add(a, b){
return a + b;
}
- (फ़ंक्शन).name
फ़ंक्शन function thefuncname(){}
का नाम thefuncname होता है, जब इसे इस तरह से घोषित किया जाता है।
function foobar(a, b){}
console.log(foobar.name);
var a = function foobar(){};
console.log(a.name);
अन्यथा, यदि किसी फ़ंक्शन को function(){}
के रूप में घोषित किया जाता है, तो फ़ंक्शन.name फ़ंक्शन को संग्रहीत करने के लिए उपयोग किया जाने वाला पहला चर है।
var a = function(){};
var b = (function(){ return function(){} });
console.log(a.name);
console.log(b.name);
यदि फ़ंक्शन में कोई चर सेट नहीं है, तो फ़ंक्शन का नाम खाली स्ट्रिंग (""
) है।
console.log((function(){}).name === "");
अंत में, जबकि वेरिएबल फ़ंक्शन को प्रारंभ में नाम सेट करने के लिए असाइन किया गया है, फ़ंक्शन पर सेट किए गए क्रमिक चर नाम नहीं बदलते हैं।
var a = function(){};
var b = a;
var c = b;
console.log(a.name);
console.log(b.name);
console.log(c.name);
- प्रदर्शन
Google के V8 और Firefox के स्पाइडरमॉन्की में कुछ माइक्रोसेकंड JIST संकलन अंतर हो सकता है, लेकिन अंततः परिणाम बिल्कुल वैसा ही है। इसे साबित करने के लिए, आइए दो रिक्त कोड स्निपेट की गति की तुलना करके माइक्रोबेंचमार्क पर JSPerf की दक्षता की जांच करें। JSPerf परीक्षण यहां पाए जाते हैं। और, jsben.ch परीक्षण यहां पाए जाते हैं। जैसा कि आप देख सकते हैं, एक ध्यान देने योग्य अंतर है जब कोई नहीं होना चाहिए। यदि आप वास्तव में मेरे जैसे एक प्रदर्शन सनकी हैं, तो दायरे में चर और कार्यों की संख्या को कम करने और विशेष रूप से बहुरूपता को समाप्त करने की कोशिश करते समय यह आपके लायक हो सकता है (जैसे दो अलग-अलग प्रकारों को स्टोर करने के लिए एक ही चर का उपयोग करना)।
- परिवर्तनीय परिवर्तनशीलता
जब आप किसी वैरिएबल को घोषित करने के लिए var
कीवर्ड का उपयोग करते हैं, तो आप इस तरह वैरिएबल के लिए एक अलग मान को फिर से असाइन कर सकते हैं।
(function(){
"use strict";
var foobar = function(){}; // initial value
try {
foobar = "Hello World!"; // new value
console.log("[no error]");
} catch(error) {
console.log("ERROR: " + error.message);
}
console.log(foobar, window.foobar);
})();
हालाँकि, जब हम कॉन्स्ट-स्टेटमेंट का उपयोग करते हैं, तो वेरिएबल रेफरेंस अपरिवर्तनीय हो जाता है। इसका मतलब है कि हम वेरिएबल के लिए एक नया मान निर्दिष्ट नहीं कर सकते हैं। कृपया ध्यान दें, हालांकि, यह चर की सामग्री को अपरिवर्तनीय नहीं बनाता है: यदि आप const arr = []
करते हैं, तो भी आप arr[10] = "example"
कर सकते हैं। केवल arr = "new value"
या arr = []
जैसा कुछ करने से एक त्रुटि होगी जैसा कि नीचे देखा गया है।
(function(){
"use strict";
const foobar = function(){}; // initial value
try {
foobar = "Hello World!"; // new value
console.log("[no error]");
} catch(error) {
console.log("ERROR: " + error.message);
}
console.log(foobar, window.foobar);
})();
दिलचस्प बात यह है कि अगर हम वेरिएबल को function funcName(){}
के रूप में घोषित करते हैं, तो वेरिएबल की अपरिवर्तनीयता var
के साथ घोषित करने के समान है।
(function(){
"use strict";
function foobar(){}; // initial value
try {
foobar = "Hello World!"; // new value
console.log("[no error]");
} catch(error) {
console.log("ERROR: " + error.message);
}
console.log(foobar, window.foobar);
})();
"𝗡𝗲𝗮𝗿𝗲𝘀𝘁 "
"निकटतम ब्लॉक" निकटतम "फ़ंक्शन" है (एसिंक्रोनस फ़ंक्शंस, जेनरेटर फ़ंक्शंस और एसिंक्रोनस जेनरेटर फ़ंक्शंस सहित)। हालांकि, दिलचस्प बात यह है कि एक function functionName() {}
एक var functionName = function() {}
की तरह व्यवहार करता है जब एक गैर-बंद ब्लॉक में उक्त बंद के बाहर की वस्तुओं के लिए। अवलोकन करना।
- सामान्य
var add=function(){}
try {
// typeof will simply return "undefined" if the variable does not exist
if (typeof add !== "undefined") {
add(1, 1); // just to prove it
console.log("Not a block");
}else if(add===undefined){ // this throws an exception if add doesn't exist
console.log('Behaves like var add=function(a,b){return a+b}');
}
} catch(e) {
console.log("Is a block");
}
var add=function(a, b){return a + b}
- सामान्य
function add(){}
try {
// typeof will simply return "undefined" if the variable does not exist
if (typeof add !== "undefined") {
add(1, 1); // just to prove it
console.log("Not a block");
}else if(add===undefined){ // this throws an exception if add doesn't exist
console.log('Behaves like var add=function(a,b){return a+b}')
}
} catch(e) {
console.log("Is a block");
}
function add(a, b){
return a + b;
}
- समारोह
try {
// typeof will simply return "undefined" if the variable does not exist
if (typeof add !== "undefined") {
add(1, 1); // just to prove it
console.log("Not a block");
}else if(add===undefined){ // this throws an exception if add doesn't exist
console.log('Behaves like var add=function(a,b){return a+b}')
}
} catch(e) {
console.log("Is a block");
}
(function () {
function add(a, b){
return a + b;
}
})();
- विवरण (जैसे
if
,else
,for
,while
,try
/catch
/finally
,switch
,do
/while
,with
)
try {
// typeof will simply return "undefined" if the variable does not exist
if (typeof add !== "undefined") {
add(1, 1); // just to prove it
console.log("Not a block");
}else if(add===undefined){ // this throws an exception if add doesn't exist
console.log('Behaves like var add=function(a,b){return a+b}')
}
} catch(e) {
console.log("Is a block");
}
{
function add(a, b){
return a + b;
}
}
var add=function()
के साथ एरो फंक्शन
try {
// typeof will simply return "undefined" if the variable does not exist
if (typeof add !== "undefined") {
add(1, 1); // just to prove it
console.log("Not a block");
}else if(add===undefined){ // this throws an exception if add doesn't exist
console.log('Behaves like var add=function(a,b){return a+b}')
}
} catch(e) {
console.log("Is a block");
}
(() => {
var add=function(a, b){
return a + b;
}
})();
function add()
के साथ एरो फंक्शन
try {
// typeof will simply return "undefined" if the variable does not exist
if (typeof add !== "undefined") {
add(1, 1); // just to prove it
console.log("Not a block");
}else if(add===undefined){ // this throws an exception if add doesn't exist
console.log('Behaves like var add=function(a,b){return a+b}')
}
} catch(e) {
console.log("Is a block");
}
(() => {
function add(a, b){
return a + b;
}
})();
एक और अंतर जिसका अन्य उत्तरों में उल्लेख नहीं किया गया है, वह यह है कि यदि आप अनाम फ़ंक्शन का उपयोग करते हैं
var functionOne = function() {
// Some code
};
और इसे एक निर्माता के रूप में in . के रूप में उपयोग करें
var one = new functionOne();
तब one.constructor.name
परिभाषित नहीं किया जाएगा। Function.name
गैर-मानक है लेकिन फ़ायरफ़ॉक्स, क्रोम, अन्य वेबकिट-व्युत्पन्न ब्राउज़र और IE 9+ द्वारा समर्थित है।
साथ में
function functionTwo() {
// Some code
}
two = new functionTwo();
two.constructor.name
के साथ एक स्ट्रिंग के रूप में कंस्ट्रक्टर का नाम पुनर्प्राप्त करना संभव है।
यदि आप वस्तुओं को बनाने के लिए उन कार्यों का उपयोग करेंगे, तो आपको मिलेगा:
var objectOne = new functionOne();
console.log(objectOne.__proto__); // prints "Object {}" because constructor is an anonymous function
var objectTwo = new functionTwo();
console.log(objectTwo.__proto__); // prints "functionTwo {}" because constructor is a named function
पहला वाला (फ़ंक्शन doSomething(x)) ऑब्जेक्ट नोटेशन का हिस्सा होना चाहिए।
दूसरा (var doSomething = function(x){ alert(x);}
) केवल एक अनाम फ़ंक्शन बना रहा है और इसे एक चर, doSomething
को असाइन कर रहा है। तो doSomething() फ़ंक्शन को कॉल करेगा।
आप शायद जानना चाहें कि फ़ंक्शन घोषणा और फ़ंक्शन एक्सप्रेशन क्या है।
एक फ़ंक्शन डिक्लेरेशन वैरिएबल असाइनमेंट की आवश्यकता के बिना नामित फ़ंक्शन वेरिएबल को परिभाषित करता है। फ़ंक्शन घोषणाएं स्टैंडअलोन निर्माण के रूप में होती हैं और गैर-फ़ंक्शन ब्लॉक के भीतर नेस्टेड नहीं की जा सकती हैं।
function foo() {
return 3;
}
ईसीएमए 5 (13.0) सिंटैक्स को
. के रूप में परिभाषित करता है फ़ंक्शन पहचानकर्ता (औपचारिक पैरामीटर सूची<उप>ऑप्टउप>) { FunctionBody }
उपरोक्त स्थिति में फ़ंक्शन का नाम इसके दायरे और उसके माता-पिता के दायरे में दिखाई देता है (अन्यथा यह पहुंच से बाहर होगा)।
और एक फंक्शन एक्सप्रेशन में
एक फ़ंक्शन एक्सप्रेशन एक फ़ंक्शन को एक बड़े एक्सप्रेशन सिंटैक्स (आमतौर पर एक चर असाइनमेंट) के एक भाग के रूप में परिभाषित करता है। फ़ंक्शंस एक्सप्रेशन के माध्यम से परिभाषित फ़ंक्शंस को नामित या अनाम किया जा सकता है। फंक्शन एक्सप्रेशन "फ़ंक्शन" से शुरू नहीं होने चाहिए।
// Anonymous function expression
var a = function() {
return 3;
}
// Named function expression
var a = function foo() {
return 3;
}
// Self-invoking function expression
(function foo() {
alert("hello!");
})();
ईसीएमए 5 (13.0) सिंटैक्स को
. के रूप में परिभाषित करता है फ़ंक्शन पहचानकर्ता<उप>ऑप्टउप> (औपचारिक पैरामीटर सूची<उप>ऑप्टउप>) { FunctionBody }
मैं नीचे अंतरों को सूचीबद्ध कर रहा हूं:
फ़ंक्शन घोषणा को कोड में कहीं भी रखा जा सकता है। यहां तक कि अगर इसे कोड में परिभाषा के प्रकट होने से पहले लागू किया जाता है, तो इसे निष्पादित किया जाता है क्योंकि फ़ंक्शन घोषणा स्मृति के लिए प्रतिबद्ध है या एक तरह से इसे फहराया जाता है, इससे पहले कि पृष्ठ में कोई अन्य कोड निष्पादन शुरू हो।
नीचे दिए गए फ़ंक्शन पर एक नज़र डालें:
function outerFunction() { function foo() { return 1; } return foo(); function foo() { return 2; } } alert(outerFunction()); // Displays 2
ऐसा इसलिए है क्योंकि निष्पादन के दौरान ऐसा दिखता है: -
function foo() { // The first function declaration is moved to top return 1; } function foo() { // The second function declaration is moved to top return 2; } function outerFunction() { return foo(); } alert(outerFunction()); //So executing from top to bottom, //the last foo() returns 2 which gets displayed
एक फ़ंक्शन अभिव्यक्ति, यदि इसे कॉल करने से पहले परिभाषित नहीं किया गया है, तो एक त्रुटि होगी। साथ ही, यहां फ़ंक्शन परिभाषा को शीर्ष पर नहीं ले जाया जाता है या फ़ंक्शन घोषणाओं की तरह स्मृति के लिए प्रतिबद्ध नहीं है। लेकिन जिस वेरिएबल को हम फ़ंक्शन असाइन करते हैं वह ऊपर हो जाता है और अपरिभाषित उसे असाइन कर दिया जाता है।
फ़ंक्शन एक्सप्रेशन का उपयोग करके समान फ़ंक्शन:
function outerFunction() { var foo = function() { return 1; } return foo(); var foo = function() { return 2; } } alert(outerFunction()); // Displays 1
ऐसा इसलिए है क्योंकि निष्पादन के दौरान ऐसा लगता है:
function outerFunction() { var foo = undefined; var foo = undefined; foo = function() { return 1; }; return foo (); foo = function() { // This function expression is not reachable return 2; }; } alert(outerFunction()); // Displays 1
गैर-फ़ंक्शन ब्लॉक जैसे if में फ़ंक्शन घोषणाएं लिखना सुरक्षित नहीं है क्योंकि वे पहुंच योग्य नहीं होंगे।
if (test) { function x() { doSomething(); } }
नामित फ़ंक्शन एक्सप्रेशन, जैसा कि नीचे दिया गया है, संस्करण 9 से पहले इंटरनेट एक्सप्लोरर ब्राउज़र में काम नहीं कर सकता है।
var today = function today() {return new Date()}
"नामित फ़ंक्शन स्टैक ट्रेस में दिखाई देते हैं" तर्क के प्रकाश में, आधुनिक जावास्क्रिप्ट इंजन वास्तव में अनाम कार्यों का प्रतिनिधित्व करने में काफी सक्षम हैं।
इस लेखन के अनुसार, V8, स्पाइडरमॉन्की, चक्र और नाइट्रो हमेशा नामित कार्यों को उनके नाम से संदर्भित करते हैं। वे लगभग हमेशा एक अज्ञात फ़ंक्शन को उसके पहचानकर्ता द्वारा संदर्भित करते हैं यदि उसके पास एक है।
स्पाइडरमोन्की किसी अन्य फ़ंक्शन से लौटाए गए अज्ञात फ़ंक्शन के नाम का पता लगा सकता है। बाकी नहीं कर सकते।
यदि आप वास्तव में, वास्तव में अपने इटरेटर और सफलता कॉलबैक को ट्रेस में दिखाना चाहते हैं, तो आप उनको भी नाम दे सकते हैं ...
[].forEach(function iterator() {});
लेकिन अधिकांश भाग के लिए यह जोर देने लायक नहीं है।
हार्नेस (Fiddle)
'use strict';
var a = function () {
throw new Error();
},
b = function b() {
throw new Error();
},
c = function d() {
throw new Error();
},
e = {
f: a,
g: b,
h: c,
i: function () {
throw new Error();
},
j: function j() {
throw new Error();
},
k: function l() {
throw new Error();
}
},
m = (function () {
return function () {
throw new Error();
};
}()),
n = (function () {
return function n() {
throw new Error();
};
}()),
o = (function () {
return function p() {
throw new Error();
};
}());
console.log([a, b, c].concat(Object.keys(e).reduce(function (values, key) {
return values.concat(e[key]);
}, [])).concat([m, n, o]).reduce(function (logs, func) {
try {
func();
} catch (error) {
return logs.concat('func.name: ' + func.name + '\n' +
'Trace:\n' +
error.stack);
// Need to manually log the error object in Nitro.
}
}, []).join('\n\n'));
वी 8
func.name:
Trace:
Error
at a (http://localhost:8000/test.js:4:11)
at http://localhost:8000/test.js:47:9
at Array.reduce (native)
at http://localhost:8000/test.js:44:27
func.name: b
Trace:
Error
at b (http://localhost:8000/test.js:7:15)
at http://localhost:8000/test.js:47:9
at Array.reduce (native)
at http://localhost:8000/test.js:44:27
func.name: d
Trace:
Error
at d (http://localhost:8000/test.js:10:15)
at http://localhost:8000/test.js:47:9
at Array.reduce (native)
at http://localhost:8000/test.js:44:27
func.name:
Trace:
Error
at a (http://localhost:8000/test.js:4:11)
at http://localhost:8000/test.js:47:9
at Array.reduce (native)
at http://localhost:8000/test.js:44:27
func.name: b
Trace:
Error
at b (http://localhost:8000/test.js:7:15)
at http://localhost:8000/test.js:47:9
at Array.reduce (native)
at http://localhost:8000/test.js:44:27
func.name: d
Trace:
Error
at d (http://localhost:8000/test.js:10:15)
at http://localhost:8000/test.js:47:9
at Array.reduce (native)
at http://localhost:8000/test.js:44:27
func.name:
Trace:
Error
at e.i (http://localhost:8000/test.js:17:19)
at http://localhost:8000/test.js:47:9
at Array.reduce (native)
at http://localhost:8000/test.js:44:27
func.name: j
Trace:
Error
at j (http://localhost:8000/test.js:20:19)
at http://localhost:8000/test.js:47:9
at Array.reduce (native)
at http://localhost:8000/test.js:44:27
func.name: l
Trace:
Error
at l (http://localhost:8000/test.js:23:19)
at http://localhost:8000/test.js:47:9
at Array.reduce (native)
at http://localhost:8000/test.js:44:27
func.name:
Trace:
Error
at http://localhost:8000/test.js:28:19
at http://localhost:8000/test.js:47:9
at Array.reduce (native)
at http://localhost:8000/test.js:44:27
func.name: n
Trace:
Error
at n (http://localhost:8000/test.js:33:19)
at http://localhost:8000/test.js:47:9
at Array.reduce (native)
at http://localhost:8000/test.js:44:27
func.name: p
Trace:
Error
at p (http://localhost:8000/test.js:38:19)
at http://localhost:8000/test.js:47:9
at Array.reduce (native)
at http://localhost:8000/test.js:44:27 test.js:42
मकड़ीनुमा बन्दर
func.name:
Trace:
a@http://localhost:8000/test.js:4:5
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1
func.name: b
Trace:
b@http://localhost:8000/test.js:7:9
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1
func.name: d
Trace:
d@http://localhost:8000/test.js:10:9
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1
func.name:
Trace:
a@http://localhost:8000/test.js:4:5
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1
func.name: b
Trace:
b@http://localhost:8000/test.js:7:9
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1
func.name: d
Trace:
d@http://localhost:8000/test.js:10:9
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1
func.name:
Trace:
e.i@http://localhost:8000/test.js:17:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1
func.name: j
Trace:
j@http://localhost:8000/test.js:20:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1
func.name: l
Trace:
l@http://localhost:8000/test.js:23:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1
func.name:
Trace:
m</<@http://localhost:8000/test.js:28:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1
func.name: n
Trace:
n@http://localhost:8000/test.js:33:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1
func.name: p
Trace:
p@http://localhost:8000/test.js:38:13
@http://localhost:8000/test.js:47:9
@http://localhost:8000/test.js:54:1
चक्र
func.name: undefined
Trace:
Error
at a (http://localhost:8000/test.js:4:5)
at Anonymous function (http://localhost:8000/test.js:47:9)
at Global code (http://localhost:8000/test.js:42:1)
func.name: undefined
Trace:
Error
at b (http://localhost:8000/test.js:7:9)
at Anonymous function (http://localhost:8000/test.js:47:9)
at Global code (http://localhost:8000/test.js:42:1)
func.name: undefined
Trace:
Error
at d (http://localhost:8000/test.js:10:9)
at Anonymous function (http://localhost:8000/test.js:47:9)
at Global code (http://localhost:8000/test.js:42:1)
func.name: undefined
Trace:
Error
at a (http://localhost:8000/test.js:4:5)
at Anonymous function (http://localhost:8000/test.js:47:9)
at Global code (http://localhost:8000/test.js:42:1)
func.name: undefined
Trace:
Error
at b (http://localhost:8000/test.js:7:9)
at Anonymous function (http://localhost:8000/test.js:47:9)
at Global code (http://localhost:8000/test.js:42:1)
func.name: undefined
Trace:
Error
at d (http://localhost:8000/test.js:10:9)
at Anonymous function (http://localhost:8000/test.js:47:9)
at Global code (http://localhost:8000/test.js:42:1)
func.name: undefined
Trace:
Error
at e.i (http://localhost:8000/test.js:17:13)
at Anonymous function (http://localhost:8000/test.js:47:9)
at Global code (http://localhost:8000/test.js:42:1)
func.name: undefined
Trace:
Error
at j (http://localhost:8000/test.js:20:13)
at Anonymous function (http://localhost:8000/test.js:47:9)
at Global code (http://localhost:8000/test.js:42:1)
func.name: undefined
Trace:
Error
at l (http://localhost:8000/test.js:23:13)
at Anonymous function (http://localhost:8000/test.js:47:9)
at Global code (http://localhost:8000/test.js:42:1)
func.name: undefined
Trace:
Error
at Anonymous function (http://localhost:8000/test.js:28:13)
at Anonymous function (http://localhost:8000/test.js:47:9)
at Global code (http://localhost:8000/test.js:42:1)
func.name: undefined
Trace:
Error
at n (http://localhost:8000/test.js:33:13)
at Anonymous function (http://localhost:8000/test.js:47:9)
at Global code (http://localhost:8000/test.js:42:1)
func.name: undefined
Trace:
Error
at p (http://localhost:8000/test.js:38:13)
at Anonymous function (http://localhost:8000/test.js:47:9)
at Global code (http://localhost:8000/test.js:42:1)
नाइट्रो
func.name:
Trace:
a@http://localhost:8000/test.js:4:22
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33
func.name: b
Trace:
b@http://localhost:8000/test.js:7:26
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33
func.name: d
Trace:
d@http://localhost:8000/test.js:10:26
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33
func.name:
Trace:
a@http://localhost:8000/test.js:4:22
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33
func.name: b
Trace:
b@http://localhost:8000/test.js:7:26
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33
func.name: d
Trace:
d@http://localhost:8000/test.js:10:26
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33
func.name:
Trace:
i@http://localhost:8000/test.js:17:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33
func.name: j
Trace:
j@http://localhost:8000/test.js:20:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33
func.name: l
Trace:
l@http://localhost:8000/test.js:23:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33
func.name:
Trace:
http://localhost:8000/test.js:28:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33
func.name: n
Trace:
n@http://localhost:8000/test.js:33:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33
func.name: p
Trace:
p@http://localhost:8000/test.js:38:30
http://localhost:8000/test.js:47:13
reduce@[native code]
global code@http://localhost:8000/test.js:44:33
दोनों एक फ़ंक्शन को परिभाषित करने के विभिन्न तरीके हैं। अंतर यह है कि ब्राउजर उन्हें निष्पादन संदर्भ में कैसे व्याख्या और लोड करता है।
पहला मामला फंक्शन एक्सप्रेशन का है जो केवल तभी लोड होता है जब दुभाषिया कोड की उस पंक्ति तक पहुंचता है। इसलिए यदि आप इसे निम्न की तरह करते हैं, तो आपको एक त्रुटि मिलेगी कि functionOne कोई फ़ंक्शन नहीं है।
functionOne();
var functionOne = function() {
// Some code
};
कारण यह है कि पहली पंक्ति में functionOne को कोई मान नहीं दिया गया है, और इसलिए यह अपरिभाषित है। हम इसे एक फ़ंक्शन के रूप में कॉल करने का प्रयास कर रहे हैं, और इसलिए हमें एक त्रुटि मिल रही है।
दूसरी पंक्ति में हम functionOne के लिए एक अनाम फ़ंक्शन का संदर्भ निर्दिष्ट कर रहे हैं।
दूसरा मामला फ़ंक्शन घोषणाओं का है जो किसी भी कोड को निष्पादित करने से पहले लोड होता है। तो यदि आप निम्न को पसंद करते हैं तो आपको कोई त्रुटि नहीं मिलेगी क्योंकि कोड निष्पादन से पहले घोषणा लोड हो जाती है।
functionOne();
function functionOne() {
// Some code
}
प्रदर्शन के बारे में:
V8
के नए संस्करणों ने कई अंडर-द-हूड ऑप्टिमाइज़ेशन पेश किए और इसी तरह SpiderMonkey
ने भी किया।
अभिव्यक्ति और घोषणा के बीच अब लगभग कोई अंतर नहीं है।
फ़ंक्शन एक्सप्रेशन अब तेज़ लगता है।
Anonymous
फ़ंक्शन एक्सप्रेशन बेहतर प्रदर्शन करते हैंNamed
फ़ंक्शन एक्सप्रेशन के विरुद्ध।
वे कुछ छोटे अंतरों के साथ बहुत समान हैं, पहला एक वैरिएबल है जो एक अनाम फ़ंक्शन (फ़ंक्शन डिक्लेरेशन) को सौंपा गया है और दूसरा जावास्क्रिप्ट (बेनामी फ़ंक्शन डिक्लेरेशन) में फ़ंक्शन बनाने का सामान्य तरीका है, दोनों में उपयोग, विपक्ष और पेशेवरों हैं :
<मजबूत>1. फंक्शन एक्सप्रेशन
var functionOne = function() {
// Some code
};
एक फंक्शन एक्सप्रेशन एक फ़ंक्शन को एक बड़े एक्सप्रेशन सिंटैक्स (आमतौर पर एक वैरिएबल असाइनमेंट) के एक भाग के रूप में परिभाषित करता है। फ़ंक्शंस एक्सप्रेशन के माध्यम से परिभाषित फ़ंक्शंस को नाम या अनाम किया जा सकता है। फंक्शन एक्सप्रेशन "फ़ंक्शन" से शुरू नहीं होना चाहिए (इसलिए नीचे दिए गए सेल्फ इनवोकिंग उदाहरण के आसपास के कोष्ठक)।
किसी फ़ंक्शन के लिए एक चर निर्दिष्ट करें, इसका मतलब है कि कोई होस्टिंग नहीं है, जैसा कि हम जानते हैं कि जावास्क्रिप्ट में फ़ंक्शन हो सकता है, इसका मतलब है कि उन्हें घोषित होने से पहले बुलाया जा सकता है, जबकि चर को उन तक पहुंचने से पहले घोषित करने की आवश्यकता होती है, इसलिए इस मामले में हम नहीं कर सकते हैं फ़ंक्शन को घोषित करने से पहले एक्सेस करें, यह भी एक तरीका हो सकता है कि आप अपने कार्यों को लिखते हैं, उन कार्यों के लिए जो एक और फ़ंक्शन लौटाते हैं, इस तरह की घोषणा समझ में आ सकती है, ईसीएमए 6 और इसके बाद के संस्करण में आप इसे एक तीर फ़ंक्शन को असाइन कर सकते हैं जो अनाम कार्यों को कॉल करने के लिए इस्तेमाल किया जा सकता है, घोषित करने का यह तरीका जावास्क्रिप्ट में कंस्ट्रक्टर फ़ंक्शन बनाने का एक बेहतर तरीका है।
<मजबूत>2. समारोह घोषणा
function functionTwo() {
// Some code
}
एक फंक्शन डिक्लेरेशन वैरिएबल असाइनमेंट की आवश्यकता के बिना एक नामित फ़ंक्शन वेरिएबल को परिभाषित करता है। फ़ंक्शन घोषणाएं स्टैंडअलोन निर्माण के रूप में होती हैं और गैर-फ़ंक्शन ब्लॉक के भीतर नेस्टेड नहीं की जा सकती हैं। उन्हें परिवर्तनीय घोषणाओं के भाई-बहन के रूप में सोचना मददगार है। जैसे परिवर्तनीय घोषणाएं "var" से शुरू होनी चाहिए, फ़ंक्शन घोषणाएं "फ़ंक्शन" से शुरू होनी चाहिए।
जावास्क्रिप्ट में किसी फ़ंक्शन को कॉल करने का यह सामान्य तरीका है, इस फ़ंक्शन को आपके द्वारा इसे घोषित करने से पहले भी बुलाया जा सकता है क्योंकि जावास्क्रिप्ट में सभी फ़ंक्शन फहराए जाते हैं, लेकिन यदि आपके पास 'सख्त उपयोग' है तो यह अपेक्षा के अनुरूप नहीं होगा, यह एक अच्छा तरीका है सभी सामान्य कार्यों को कॉल करने के लिए जो लाइनों में बड़े नहीं हैं और न ही एक कंस्ट्रक्टर फ़ंक्शन हैं।
इसके अलावा, अगर आपको जावास्क्रिप्ट में उत्थापन कैसे काम करता है, इस बारे में अधिक जानकारी चाहिए, तो नीचे दिए गए लिंक पर जाएं:
https://developer.mozilla.org/en-US/docs/Glossary/Hoisting
यह फ़ंक्शन घोषित करने के केवल दो संभावित तरीके हैं, और दूसरे तरीके से, आप घोषणा से पहले फ़ंक्शन का उपयोग कर सकते हैं।
new Function()
का उपयोग फंक्शन की बॉडी को एक स्ट्रिंग में पास करने के लिए किया जा सकता है। और इसलिए इसका उपयोग गतिशील कार्यों को बनाने के लिए किया जा सकता है। साथ ही स्क्रिप्ट को निष्पादित किए बिना स्क्रिप्ट पास करना।
var func = new Function("x", "y", "return x*y;");
function secondFunction(){
var result;
result = func(10,20);
console.log ( result );
}
secondFunction()
let
याconst
का उपयोग एक वेरिएबल को परिभाषित करने के लिए करता है जो उसके भीतर एक फ़ंक्शन द्वारा बंद किया गया था, और उस नियम को लागू करना लगातार अपरिहार्य होने पर ही इसे लागू करने से बेहतर है।var functionOne
और साथ हीfunction functionTwo
कुछ हद तक फहराए जाते हैं - यह सिर्फ इतना है कि functionOne को अपरिभाषित पर सेट किया गया है (आप इसे आधा-उत्थापन कह सकते हैं, चर हमेशा केवल उस डिग्री तक फहराए जाते हैं) जबकि फ़ंक्शन फ़ंक्शन दो पूरी तरह से फहराया गया है जिसमें इसे परिभाषित और घोषित किया गया है। किसी ऐसी चीज़ को लागू करना जो अपरिभाषित हो, निश्चित रूप से एक टाइप एरर फेंक दें।