सवाल var functionName = function () {} बनाम फ़ंक्शन फ़ंक्शननाम () {}


मैंने हाल ही में किसी और के जावास्क्रिप्ट कोड को बनाए रखना शुरू कर दिया है। मैं बग फिक्स कर रहा हूं, सुविधाओं को जोड़ रहा हूं और कोड को साफ करने और इसे और अधिक सुसंगत बनाने की कोशिश कर रहा हूं।

पिछला डेवलपर फ़ंक्शन घोषित करने के दो तरीकों का उपयोग करता है और यदि इसके पीछे कोई कारण नहीं है तो मैं काम नहीं कर सकता हूं।

दो तरीके हैं:

var functionOne = function() {
    // Some code
};
function functionTwo() {
    // Some code
}

इन दो अलग-अलग तरीकों का उपयोग करने के कारण क्या हैं और प्रत्येक के पेशेवर और विपक्ष क्या हैं? क्या ऐसी कोई चीज है जो एक विधि के साथ की जा सकती है जिसे दूसरे के साथ नहीं किया जा सकता है?


6059
2017-12-03 11:31


मूल


permadi.com/tutorial/jsFunc/index.html जावास्क्रिप्ट कार्यों के बारे में बहुत अच्छा पेज है - uzay95
यह संबंधित है अति उत्कृष्ट लेख पर नामित फंक्शन अभिव्यक्तियां। - Phrogz
@ सीएमएस इस आलेख का संदर्भ देता है: kangax.github.com/nfe/#expr-vs-decl - Upperstage
ऐसी दो चीजें हैं जिनके बारे में आपको अवगत होना चाहिए: # 1 जावास्क्रिप्ट में, घोषणाएं फेंक दी जाती हैं। जिसका अर्थ है कि var a = 1; var b = 2; हो जाता है var a; var b; a = 1; b = 2। तो जब आप फंक्शन घोषित करते हैं, तो यह घोषित हो जाता है लेकिन इसका मूल्य तुरंत सेट नहीं होता है। जबकि समारोह के बाद से केवल एक घोषणा है, यह दायरे के शीर्ष पर डाल दिया जाता है। # 2 functionTwo आपको नाम संपत्ति तक पहुंचने देता है और इससे कुछ डीबग करने का प्रयास करते समय बहुत मदद मिलती है। - xavierm02
ओह और बीटीडब्ल्यू, सही वाक्यविन्यास एक ";" के साथ है असाइनमेंट के बाद और घोषणा के बाद। जैसे function f(){} बनाम var f = function(){};। - xavierm02


जवाब:


अंतर यह है कि functionOne एक फ़ंक्शन अभिव्यक्ति है और इसलिए केवल उस रेखा तक पहुंचने पर ही परिभाषित किया जाता है, जबकि functionTwo एक फ़ंक्शन घोषणा है और जैसे ही इसके आस-पास के फ़ंक्शन या स्क्रिप्ट को निष्पादित किया जाता है (इसके कारण उत्थापन)।

उदाहरण के लिए, एक फ़ंक्शन अभिव्यक्ति:

// TypeError: functionOne is not a function
functionOne();

var functionOne = function() {
  console.log("Hello!");
};

और, एक समारोह घोषणा:

// Outputs: "Hello!"
functionTwo();

function functionTwo() {
  console.log("Hello!");
}

इसका मतलब यह भी है कि आप फ़ंक्शन घोषणाओं का उपयोग करके फ़ंक्शंस को सशर्त रूप से परिभाषित नहीं कर सकते हैं:

if (test) {
   // Error or misbehavior
   function functionThree() { doSomething(); }
}

उपर्युक्त वास्तव में परिभाषित करता है functionThree के बावजूद testमूल्य - जब तक use strict असल में है, इस मामले में यह बस एक त्रुटि उठाता है।


4493
2017-12-03 11:37



@ ग्रेग: वैसे, अंतर केवल इतना नहीं है कि उन्हें अलग-अलग समय पर पार्स किया जाता है। अनिवार्य रूप से, आपका functionOne केवल एक चर है जिसमें एक अज्ञात फ़ंक्शन है, जबकि functionTwo वास्तव में एक नामित समारोह है। कॉल .toString() अंतर देखने के लिए दोनों पर। यह कुछ मामलों में महत्वपूर्ण है जहां आप प्रोग्राम के रूप में प्रोग्राम का नाम प्राप्त करना चाहते हैं। - Jason Bunting
दोनों अलग हैं। पहला एक है function expression दूसरा एक है function declaration। आप यहां विषय पर और अधिक पढ़ सकते हैं: javascriptweblog.wordpress.com/2010/07/06/... - Michal Kuklis
@ ग्रेग पार्स टाइम बनाम रन टाइम से संबंधित आपके उत्तर का हिस्सा सही नहीं है। जावास्क्रिप्ट में, कार्य घोषणाएं पार्स समय के दौरान परिभाषित नहीं की जाती हैं, लेकिन रन टाइम के दौरान। प्रक्रिया इस प्रकार है: स्रोत कोड पार्स किया गया है -> जावास्क्रिप्ट प्रोग्राम का मूल्यांकन किया जाता है -> वैश्विक निष्पादन संदर्भ प्रारंभ किया गया है -> घोषणा बाध्यकारी त्वरण किया जाता है। इस प्रक्रिया के दौरान समारोह घोषणाएं तत्काल होती हैं (चरण 5 देखें अध्याय 10.5)। - Šime Vidas
इस घटना के लिए शब्दावली hoisting के रूप में जाना जाता है। - Colin Pear
इस जवाब में यूजीन के कुछ भी नहीं है। और यह पार्स-टाइम बनाम रन-टाइम कथन के साथ काफी भ्रामक है। - Griffin


सबसे पहले मैं ग्रेग को सही करना चाहता हूं: function abc(){} नाम भी है - नाम abc उस दायरे में परिभाषित किया गया है जहां इस परिभाषा का सामना किया गया है। उदाहरण:

function xyz(){
  function abc(){};
  // abc is defined here...
}
// ...but not here

दूसरा, दोनों शैलियों को गठबंधन करना संभव है:

var xyz = function abc(){};

xyz सामान्य के रूप में परिभाषित किया जा रहा है, abc सभी ब्राउज़रों में अपरिभाषित है लेकिन इंटरनेट एक्सप्लोरर - परिभाषित होने पर भरोसा न करें। लेकिन इसे अपने शरीर के अंदर परिभाषित किया जाएगा:

var xyz = function abc(){
  // xyz is visible here
  // abc is visible here
}
// xyz is visible here
// abc is undefined here

यदि आप सभी ब्राउज़रों पर कार्यों को उपनाम करना चाहते हैं, तो इस तरह की घोषणा का उपयोग करें:

function abc(){};
var xyz = abc;

इस मामले में, दोनों xyz तथा abc एक ही वस्तु के उपनाम हैं:

console.log(xyz === abc); // prints "true"

संयुक्त शैली का उपयोग करने के लिए एक अनिवार्य कारण फ़ंक्शन ऑब्जेक्ट्स का "नाम" विशेषता है (इंटरनेट एक्सप्लोरर द्वारा समर्थित नहीं है)। असल में जब आप एक समारोह को परिभाषित करते हैं

function abc(){};
console.log(abc.name); // prints "abc"

इसका नाम स्वचालित रूप से असाइन किया गया है। लेकिन जब आप इसे परिभाषित करते हैं

var abc = function(){};
console.log(abc.name); // prints ""

इसका नाम खाली है - हमने एक अनाम कार्य बनाया है और इसे कुछ चर के लिए असाइन किया है।

संयुक्त शैली का उपयोग करने का एक और अच्छा कारण बाहरी उपयोगकर्ताओं के लिए एक लंबा गैर-विरोधी नाम प्रदान करते समय स्वयं को संदर्भित करने के लिए एक छोटा आंतरिक नाम उपयोग करना है:

// Assume really.long.external.scoped is {}
really.long.external.scoped.name = function shortcut(n){
  // Let it call itself recursively:
  shortcut(n - 1);
  // ...
  // Let it pass itself as a callback:
  someFunction(shortcut);
  // ...
}

ऊपर दिए गए उदाहरण में हम बाहरी नाम के साथ ऐसा ही कर सकते हैं, लेकिन यह बहुत ही कमजोर (और धीमी) होगी।

(खुद को संदर्भित करने का एक और तरीका उपयोग करना है arguments.callee, जो अभी भी अपेक्षाकृत लंबा है, और सख्त मोड में समर्थित नहीं है।)

गहराई से, जावास्क्रिप्ट दोनों बयान अलग-अलग व्यवहार करता है। यह एक समारोह घोषणा है:

function abc(){}

abc यहां वर्तमान दायरे में हर जगह परिभाषित किया गया है:

// We can call it here
abc(); // Works

// Yet, it is defined down there.
function abc(){}

// We can call it again
abc(); // Works

इसके अलावा, यह एक के माध्यम से फहराया return बयान:

// We can call it here
abc(); // Works
return;
function abc(){}

यह एक समारोह अभिव्यक्ति है:

var xyz = function(){};

xyz यहां असाइनमेंट के बिंदु से परिभाषित किया गया है:

// We can't call it here
xyz(); // UNDEFINED!!!

// Now it is defined
xyz = function(){}

// We can call it here
xyz(); // works

फंक्शन घोषणा बनाम फ़ंक्शन अभिव्यक्ति वास्तविक कारण है कि ग्रेग द्वारा प्रदर्शित एक अंतर क्यों है।

मजेदार तथ्य:

var xyz = function abc(){};
console.log(xyz.name); // Prints "abc"

निजी तौर पर, मैं "फ़ंक्शन अभिव्यक्ति" घोषणा पसंद करता हूं क्योंकि इस तरह से मैं दृश्यता को नियंत्रित कर सकता हूं। जब मैं इस तरह के समारोह को परिभाषित करता हूं

var abc = function(){};

मुझे पता है कि मैंने स्थानीय रूप से फ़ंक्शन को परिभाषित किया है। जब मैं इस तरह के समारोह को परिभाषित करता हूं

abc = function(){};

मुझे पता है कि मैंने इसे विश्व स्तर पर परिभाषित किया है कि मैंने परिभाषित नहीं किया है abc कहीं भी scopes की श्रृंखला में। परिभाषा की यह शैली तब भी लचीला है जब अंदर उपयोग किया जाता है eval()। परिभाषा के दौरान

function abc(){};

संदर्भ पर निर्भर करता है और आपको अनुमान लगा सकता है कि इसे वास्तव में परिभाषित किया गया है, खासकर मामले में eval() - जवाब है: यह ब्राउज़र पर निर्भर करता है।


1805
2017-12-03 17:43



मैं RoBorg का उल्लेख करता हूं लेकिन वह कहीं भी नहीं मिला है। सरल: RoBorg === ग्रेग। इस तरह इंटरनेट की उम्र में इतिहास को फिर से लिखा जा सकता है। ;-) - Eugene Lazutkin
var xyz = function abc () {}; console.log (xyz === abc); मेरे द्वारा परीक्षण किए गए सभी ब्राउज़रों (सफारी 4, फ़ायरफ़ॉक्स 3.5.5, ओपेरा 10.10) मुझे "अपरिभाषित चर: एबीसी" देता है। - NVI
कुल मिलाकर मुझे लगता है कि यह पोस्ट अंतर घोषणा और कार्य घोषणा का उपयोग करने के फायदों को समझाने का एक अच्छा काम करता है। मैं एक चर के लिए फ़ंक्शन अभिव्यक्ति असाइनमेंट का उपयोग करने के लाभों तक असहमत होने के लिए सहमत हूं, खासकर जब से "लाभ" वैश्विक इकाई घोषित करने का एक वकील प्रतीत होता है ... और हर कोई जानता है कि आपको वैश्विक नामस्थान को अव्यवस्थित नहीं करना चाहिए , सही? ;-) - natlee75
नामित फ़ंक्शन का उपयोग करने का एक बड़ा कारण यह है कि डिबगर्स आपके कॉल स्टैक या स्टैक ट्रेस को समझने में सहायता के लिए नाम का उपयोग कर सकते हैं। जब आप कॉल स्टैक को देखते हैं तो यह बेकार होता है और "अज्ञात फ़ंक्शन" 10 स्तरों को गहराई से देखता है ... - goat
@ एंटीमोनी एक समारोह घोषणा एक ब्लॉक के समान नहीं है। यह बेहतर समझा जाना चाहिए: stackoverflow.com/questions/17409945/... - Cypher


यहां फ़ंक्शंस बनाने वाले मानक रूपों पर रूंडउन है: (मूल रूप से एक और प्रश्न के लिए लिखा गया है, लेकिन कैननिकल प्रश्न में स्थानांतरित होने के बाद अनुकूलित किया गया।)

शर्तें:

त्वरित सूची:

  • समारोह घोषणा

  • "बेनामी" 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 के अनुसार, विनिर्देश कहता है कि क्या करना है। वास्तव में, यह करने के लिए तीन अलग-अलग चीजें देता है:

  1. अगर ढीले मोड में नहीं एक वेब ब्राउज़र पर, जावास्क्रिप्ट इंजन एक काम करना चाहिए
  2. यदि किसी वेब ब्राउज़र पर ढीले मोड में, जावास्क्रिप्ट इंजन को कुछ और करना है
  3. मैं फ़िन कठोर मोड (ब्राउज़र या नहीं), जावास्क्रिप्ट इंजन को अभी तक एक और चीज करना है

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

"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');
};

सभी अभिव्यक्तियों की तरह, यह मूल्यांकन किया जाता है जब यह कोड के चरण-दर-चरण निष्पादन में पहुंच जाता है।

ईएस 5 में, इस रचना के फ़ंक्शन का कोई नाम नहीं है (यह अनाम है)। 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"

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

एक्सेसर फ़ंक्शन प्रारंभकर्ता (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() कहते हैं? यह एक समारोह है।

तीर कार्यों के बारे में कुछ चीजें:

  1. उनके पास अपना नहीं है this। इसके बजाए, वे बंद करो  this संदर्भ के जहां वे परिभाषित हैं। (वे भी बंद हो जाते हैं arguments और, जहां प्रासंगिक, super।) इसका मतलब है कि this उनके भीतर समान है this जहां वे बनाए जाते हैं, और बदला नहीं जा सकता है।

  2. जैसा कि आपने उपरोक्त के साथ देखा होगा, आप कीवर्ड का उपयोग नहीं करते हैं 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() {
    }
};

ईएस 5 और पहले के बराबर होगा:

var o = {
    foo: function foo() {
    }
};

में कन्स्ट्रक्टर और विधि घोषणाएं 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


544
2018-03-04 13:35



फिर नाम w बस अनदेखा किया जाता है? - BiAiB
@PellePenna: कई नामों के लिए फ़ंक्शन नाम उपयोगी हैं। मेरे विचार में दो biggies रिकर्सन हैं, और समारोह के नाम कॉल स्टैक, अपवाद निशान, और इस तरह दिखाया जा रहा है। - T.J. Crowder
यह अब स्वीकार्य उत्तर होना चाहिए। यह उपर्युक्त की तुलना में बहुत अधिक हालिया है। - Chaim Eliyah
@CimimEliyah - "स्वीकार करने का मतलब यह नहीं है कि यह सबसे अच्छा जवाब है, इसका मतलब यह है कि यह उस व्यक्ति के लिए काम करता है जिसने पूछा।" स्रोत - ScrapCode
@ एआर .: काफी सच है। आश्चर्यजनक रूप से, हालांकि, इसके ठीक ऊपर यह कहता है "सबसे अच्छे उत्तर पहले दिखाई देते हैं ताकि वे हमेशा ढूंढ सकें।" चूंकि स्वीकृत उत्तर पहले से ही उच्च वोट वाले उत्तरों के ऊपर दिखाता है, इसलिए दौरा कुछ हद तक आत्म-विरोधाभासी हो सकता है। ;-) कुछ भी गलत, अगर हम वोटों द्वारा "सर्वश्रेष्ठ" निर्धारित करते हैं (जो विश्वसनीय नहीं है, यह वही है जो हमें मिला है), "सर्वश्रेष्ठ" उत्तर केवल पहले दिखाए जाते हैं यदि आप "वोट" टैब का उपयोग कर रहे हैं - अन्यथा, जो उत्तर पहले हैं वे सक्रिय हैं, या सबसे पुराने हैं। - T.J. Crowder


वैश्विक संदर्भ के बारे में बोलते हुए, दोनों var बयान और ए FunctionDeclaration अंत में एक बना देगा गैर deleteable वैश्विक वस्तु पर संपत्ति, लेकिन दोनों का मूल्य ओवरराइट किया जा सकता है

दो तरीकों के बीच सूक्ष्म अंतर यह है कि जब परिवर्तनीय इंस्टेंटेशन प्रक्रिया चलती है (वास्तविक कोड निष्पादन से पहले) सभी पहचानकर्ताओं के साथ घोषित किया गया var के साथ शुरू किया जाएगा undefined, और द्वारा उपयोग किए जाने वाले FunctionDeclarationउस पल के बाद से उपलब्ध होगा, उदाहरण के लिए:

 alert(typeof foo); // 'function', it's already available
 alert(typeof bar); // 'undefined'
 function foo () {}
 var bar = function () {};
 alert(typeof bar); // 'function'

का असाइनमेंट bar  FunctionExpression रनटाइम तक होता है।

एक वैश्विक संपत्ति ए द्वारा बनाई गई FunctionDeclaration एक परिवर्तनीय मूल्य की तरह किसी भी समस्या के बिना ओवरराइट किया जा सकता है, उदाहरण:

 function test () {}
 test = null;

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

आपके संपादित पहले उदाहरण के बारे में (foo = function() { alert('hello!'); };), यह एक अविकसित असाइनमेंट है, मैं आपको हमेशा उपयोग करने के लिए प्रोत्साहित करता हूं var कीवर्ड।

एक असाइनमेंट के साथ, बिना var कथन, यदि संदर्भित पहचानकर्ता स्कोप श्रृंखला में नहीं मिलता है, तो यह एक बन जाएगा deleteable वैश्विक वस्तु की संपत्ति।

इसके अलावा, अविकसित असाइनमेंट फेंक देते हैं ReferenceError ईसीएमएस्क्रिप्ट 5 के तहत सख्त मोड

एक अवश्य पढ़ने की बात:

ध्यान दें: यह जवाब से विलय कर दिया गया है एक और प्रश्न, जिसमें ओपी से प्रमुख संदेह और गलत धारणा थी कि पहचानकर्ताओं ने घोषणा की थी FunctionDeclaration, ओवरराइट नहीं किया जा सका जो मामला नहीं है।


133
2017-08-08 19:32



मुझे नहीं पता था कि जावास्क्रिप्ट में कार्यों को ओवरराइट किया जा सकता है! इसके अलावा, वह पार्स ऑर्डर मेरे लिए बड़ी बिक्री बिंदु है। मुझे लगता है कि मुझे यह देखने की ज़रूरत है कि मैं कैसे काम करता हूं। - Xeoncross
+0 नाम "फ़ंक्शन एक्सप्रेशन डेमस्टिफाइड" आलेख में 404 के रूप में है। संभावित दर्पण ?: kangax.github.com/nfe - Mr_Chimp
@ सीएमएस अच्छा है। ध्यान रखें हालांकि मैंने मूल को कभी नहीं देखा है, इसलिए मुझे नहीं पता कि यह एक दर्पण है या एक ही शीर्षक के साथ सिर्फ एक और लेख है! - Mr_Chimp
@Mr_Chimp मुझे यकीन है कि यह है ,वेबैकमाचिन कह रहा है कि इसे क्रॉल समय पर 302 मिल गया है और आपके द्वारा प्रदान किए गए लिंक के लिए पुनर्निर्देशन था। - John


आपके द्वारा पोस्ट किए गए दो कोड स्निपेट, लगभग सभी उद्देश्यों के लिए, वैसे ही व्यवहार करेंगे।

हालांकि, व्यवहार में अंतर यह है कि पहले संस्करण के साथ (var functionOne = function() {}), उस फ़ंक्शन को कोड में उस बिंदु के बाद ही बुलाया जा सकता है।

दूसरे संस्करण के साथ (function functionTwo()), फ़ंक्शन कोड के लिए उपलब्ध है जो ऊपर चलाता है जहां फ़ंक्शन घोषित किया जाता है।

ऐसा इसलिए है क्योंकि पहले संस्करण के साथ, फ़ंक्शन को चर के लिए असाइन किया गया है foo चलने के समय पर। दूसरे में, फ़ंक्शन उस पहचानकर्ता को सौंपा गया है, foo, पार्स समय पर।

अधिक तकनीकी जानकारी

जावास्क्रिप्ट में कार्यों को परिभाषित करने के तीन तरीके हैं।

  1. आपका पहला स्निपेट ए दिखाता है समारोह अभिव्यक्ति। इसमें उपयोग करना शामिल है "फंक्शन" ऑपरेटर फ़ंक्शन बनाने के लिए - उस ऑपरेटर का परिणाम किसी भी चर या ऑब्जेक्ट प्रॉपर्टी में संग्रहीत किया जा सकता है। फ़ंक्शन अभिव्यक्ति उस तरह शक्तिशाली है। फ़ंक्शन अभिव्यक्ति को अक्सर "अज्ञात फ़ंक्शन" कहा जाता है, क्योंकि इसका नाम नहीं होना चाहिए,
  2. आपका दूसरा उदाहरण ए है समारोह घोषणा। यह उपयोग करता है "फ़ंक्शन" कथन एक समारोह बनाने के लिए। समारोह पार्स समय पर उपलब्ध कराया गया है और उस दायरे में कहीं भी कहा जा सकता है। आप इसे बाद में एक चर या ऑब्जेक्ट प्रॉपर्टी में स्टोर कर सकते हैं।
  3. एक समारोह को परिभाषित करने का तीसरा तरीका है "फंक्शन ()" कन्स्ट्रक्टर, जो आपकी मूल पोस्ट में नहीं दिखाया गया है। इसका उपयोग करने की अनुशंसा नहीं की जाती है क्योंकि यह वैसे ही काम करता है eval(), जिसमें इसकी समस्याएं हैं।

111
2018-04-20 04:54





एक बेहतर स्पष्टीकरण ग्रेग का जवाब

functionTwo();
function functionTwo() {
}

कोई त्रुटि क्यों नहीं? हमें हमेशा सिखाया जाता था कि अभिव्यक्ति को ऊपर से नीचे तक निष्पादित किया जाता है (??)

इसलिये:

फंक्शन घोषणाएं और परिवर्तनीय घोषणाएं हमेशा स्थानांतरित होती हैं (hoisted) जावास्क्रिप्ट दुभाषिया द्वारा उनके युक्त दायरे के शीर्ष पर अदृश्य रूप से। फ़ंक्शन पैरामीटर और भाषा-परिभाषित नाम, जाहिर है, पहले से ही वहां हैं। बेन चेरी

इसका मतलब है कि इस तरह का कोड:

functionOne();                  ---------------      var functionOne;
                                | is actually |      functionOne();
var functionOne = function(){   | interpreted |-->
};                              |    like     |      functionOne = function(){
                                ---------------      };

ध्यान दें कि घोषणाओं का असाइनमेंट हिस्सा फहराया नहीं गया था। केवल नाम फहराया गया है।

लेकिन समारोह घोषणाओं के मामले में, पूरे फंक्शन बॉडी को भी फेंक दिया जाएगा:

functionTwo();              ---------------      function functionTwo() {
                            | is actually |      };
function functionTwo() {    | interpreted |-->
}                           |    like     |      functionTwo();
                            ---------------

91
2017-08-09 02:45



समारोह विषय के बारे में स्पष्ट जानकारी के लिए HI suhail धन्यवाद। अब मेरा सवाल यह है कि घोषणा पदानुक्रम में पहली घोषणा कौन सा है, चाहे वेरिएबल घोषणा (फ़ंक्शनऑन) या फ़ंक्शन घोषणा (फ़ंक्शन दो)? - Sharathi RB


अन्य टिप्पणीकारों ने उपरोक्त दो प्रकारों के अर्थपूर्ण अंतर को पहले ही कवर कर लिया है। मैं एक स्टाइलिस्ट अंतर को नोट करना चाहता था: केवल "असाइनमेंट" भिन्नता किसी अन्य ऑब्जेक्ट की संपत्ति सेट कर सकती है।

मैं अक्सर इस तरह के पैटर्न के साथ जावास्क्रिप्ट मॉड्यूल का निर्माण:

(function(){
    var exports = {};

    function privateUtil() {
            ...
    }

    exports.publicUtil = function() {
            ...
    };

    return exports;
})();

इस पैटर्न के साथ, आपके सार्वजनिक कार्य सभी असाइनमेंट का उपयोग करेंगे, जबकि आपके निजी कार्य घोषणा का उपयोग करेंगे।

(ध्यान दें कि कथन के बाद असाइनमेंट को अर्धविराम की आवश्यकता होनी चाहिए, जबकि घोषणा इसे प्रतिबंधित करती है।)


83
2018-03-03 19:19



yuiblog.com/blog/2007/06/12/module-pattern जहां तक ​​मैं कह सकता हूं, मॉड्यूल पैटर्न के लिए प्राथमिक संदर्भ है। (हालांकि वह लेख उपयोग करता है var foo = function(){...} निजी चर के लिए भी वाक्यविन्यास। - Sean McMillan
यह वास्तव में आईई के कुछ पुराने संस्करणों में पूरी तरह से सच नहीं है। (function window.onload() {} एक बात थी।) - Ry-♦