Var functionName = function () {} vs function functionName () {}

Kamakailan lamang, sinimulan kong suportahan ang JavaScript code ng isa pang gumagamit. Nukumpuni ko ang mga error, idagdag ang mga pag-andar, at subukan din upang malinis ang code at gawin itong mas pare-pareho.

Ang nakaraang nag-develop ay gumagamit ng dalawang paraan upang idedeklara ang mga pag-andar, at hindi ko malaman kung may dahilan para dito o hindi.

Dalawang paraan ang:

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

Ano ang mga dahilan sa paggamit ng dalawang magkakaibang pamamaraan at ano ang mga kalamangan at kahinaan ng bawat isa sa kanila? Mayroon bang isang bagay na maaaring gawin sa isang paraan na hindi maaaring gawin sa iba?

6296
03 дек. Itinanong ni Richard Garside ang 03 Dis 2008-12-03 14:31 '08 at 2:31 pm 2008-12-03 14:31
@ 37 sagot
  • 1
  • 2

Ang pagkakaiba ay ang functionOne ay isang pagpapahayag ng isang function at samakatuwid ito ay tinutukoy lamang kapag ang linya na ito ay naabot, habang functionTwo ay isang function na deklarasyon at ay tinutukoy sa lalong madaling ang nakapalibot na function o script ay pinaandar (dahil sa pag- aangat ).

Halimbawa, ang function na expression:

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

Nangangahulugan din ito na hindi mo maaaring kondisyon na tukuyin ang mga function gamit ang mga deklarasyon ng function:

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

Ang nasa itaas ay talagang tumutukoy sa functionThree anuman ang halaga ng test - maliban kung ang use strict aksyon, kung saan ang kaso ay nagiging sanhi lamang ng isang error.

4669
03 дек. sumagot na ibinigay ng Greg 03 dec. 2008-12-03 14:37 '08 at 2:37 pm 2008-12-03 14:37

Una gusto kong ayusin ang Greg: function abc(){} limitado din; - ang pangalan ng abc ay tinukoy sa lugar kung saan matatagpuan ang kahulugan na ito. Halimbawa:

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

Pangalawa, maaari mong pagsamahin ang parehong estilo:

 var xyz = function abc(){}; 

xyz ay tinutukoy gaya ng dati, abc - hindi natukoy sa lahat ng mga browser, ngunit ang Internet Explorer - ay hindi umaasa sa kahulugan nito. Ngunit siya ay tinukoy sa loob ng kanyang katawan:

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

Kung nais mong gumamit ng mga pseudonym sa lahat ng mga browser, gamitin ang ganitong uri ng ad:

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

Sa kasong ito, ang parehong xyz at abc ay mga alyas ng parehong bagay:

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

Ang isa sa mga nakakahimok na dahilan para sa paggamit ng estilo ng pinagsama ay ang "pangalan" na attribute para sa mga bagay sa pag-andar ( hindi sinusuportahan ng Internet Explorer ). Talaga, kapag tinukoy mo ang isang function tulad ng

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

awtomatikong itinalaga ang kanyang pangalan. Ngunit kapag tinutukoy mo ito bi>

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

ang pangalan nito ay wa>

Ang isa pang magandang dahilan upang gamitin ang estilo ng pinagsama ay ang paggamit ng isang maikling panloob na pangalan upang tumukoy dito, na nagbibigay ng isang mahabang di-magkasalungat na pangalan para sa mga panlabas na gumagamit:

 // 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); // ... } 

Sa halimbawa sa itaas, maaari naming gawin ang parehong sa panlabas na pangalan, ngunit ito ay magiging masyadong masalimuot (at mas mabagal).

(Ang isa pang paraan upang matugunan ang iyong sarili ay ang paggamit ng arguments.callee , na medyo mahaba at hindi suportado sa mahigpit na mode.)

Pababa, ang JavaScript ay humahawak ng parehong pahayag nang iba. Ito ay isang deklarasyon ng pag-andar:

border=0
 function abc(){} 

abc dito ay tinukoy sa lahat ng dako sa kasalukuyang lugar:

 // We can call it here abc(); // Works // Yet, it is defined down there. function abc(){} // We can call it again abc(); // Works 

Bi>return :

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

Ito ay isang function na expression:

 var xyz = function(){}; 

xyz ay tinukoy dito mula sa patutunguhan:

 // We can't call it here xyz(); // UNDEFINED!!! // Now it is defined xyz = function(){} // We can call it here xyz(); // works 

Ang function na deklarasyon at ang function na expression ay ang tunay na dahilan na may isang pagkakaiba, nagpakita sa pamamagitan ng Greg.

Kasayahan katotohanan:

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

Sa personal, mas gusto ko ang deklarasyon ng "pagpapahayag ng pag-andar," dahil sa ganitong paraan maaari kong kontrolin ang visibility. Kapag tinukoy ko ang isang function ng uri

 var abc = function(){}; 

Alam ko na tinukoy ko ang pag-andar nang lokal. Kapag tinukoy ko ang isang function ng uri

 abc = function(){}; 

Alam ko na tinukoy ko ito sa buong mundo, na nagpapahiwatig na hindi ko tinukoy ang abc saanman sa hanay ng mga rehiyon. Ang estilo ng kahulugan na ito ay matatag kahit na ginamit sa loob ng eval() . Kahit na ang kahulugan

 function abc(){}; 

depende sa konteksto at maaaring iwanan kang nagtataka kung saan ito tinukoy, lalo na sa kaso ng eval() - Sagot: Depende ito sa browser.

1846
03 дек. Ang sagot ay ibinigay sa pamamagitan ng Eugene Lazutkin 03 dec. 2008-12-03 20:43 '08 at 8:43 pm 2008-12-03 20:43

Narito ang isang buod ng karaniwang mga form na lumikha ng mga function: (Orihinal na nakasulat para sa isa pang tanong, ngunit inangkop pagkatapos ng paglipat sa canonical na tanong.)

Mga Tuntunin:

Mabilis na listahan:

  • Ang deklarasyon ng function

  • "Anonymous" function Expression (na, sa kabila ng termino, kung minsan ay lumilikha ng mga function na may mga pangalan)

  • Pinangalanang function Named

  • Access Function Initializer (ES5 +)

  • Arrow function expression (ES2015 +) (kung saan, tulad ng anonymous function na expression, ay hindi naglalaman ng isang tahasang pangalan at maaaring lumikha ng mga function na may mga pangalan)

  • Pamamaraan deklarasyon sa object initializer (ES2015 +)

  • Mga tagatukoy ng constructor at pamamaraan sa class (ES2015 +)

Ang deklarasyon ng function

Ang unang form ay isang deklarasyon ng function na mukhang ganito:

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

Isang deklarasyon ng pag-andar ay isang ad; ito ay hindi isang pahayag o pagpapahayag. Kaya't hindi ka sumunod sa kanya ; (kahit na ito ay hindi nakakapinsala).

Ang isang deklarasyon ng pag-andar ay naproseso kapag ang pagpapatupad ay pumasok sa konteksto kung saan lumilitaw ito bago isagawa ang anumang hakbang na code. Ang function na lumilikha nito ay itinalaga sa sarili nitong pangalan ( x sa halimbawa sa itaas), at ang pangalan na ito ay inilalagay sa lugar kung saan lumilitaw ang pahayag.

Dahil pinoproseso ito bago ang anumang hakbang na code sa parehong konteksto, maaari kang gumawa ng ganito:

 x(); // Works even though it above the declaration function x() { console.log('x'); } 

Bago ang ES2015, ang detalye ay hindi sumasakop sa kung ano ang dapat gawin ng engine ng JavaScript kung inilagay mo ang function declaration sa loob ng istraktura ng control, halimbawa, try , if , switch , while , atbp Halimbawa:

 if (someCondition) { function foo() { // <===== HERE THERE } // <===== BE DRAGONS } 

At dahil pinoproseso ito bago patakbuhin ang sunud-sunod na code, mahirap malaman kung ano ang gagawin kapag nasa istraktura ng pamamahala.

Kahit na ito ay hindi ipinahiwatig bago ES2015, ito ay isang wastong extension upang suportahan ang mga deklarasyon ng pag-andar sa mga bloke. Sa kasamaang palad (at hindi maaaring hindi), iba't ibang mga engine ang ginawa ng iba't ibang mga bagay.

Simula sa ES2015, ang detalye ay nagsasabi kung ano ang gagawin. Sa katunayan, nagbibigay ito ng tatlong hiwalay na aksyon:

  1. Kung sa libreng mode ay wala sa web browser, dapat gawin ng JavaScript engine ang isang bagay.
  2. Kung sa libreng mode sa isang web browser, ang JavaScript engine ay dapat gumawa ng iba pa.
  3. Kung sa mahigpit na mode (browser o hindi), dapat gawin ng JavaScript engine ang isa pang bagay.

Ang mga patakaran para sa mga libreng mode ay nakakalito, ngunit sa mahigpit na mode, ang mga function declarations sa mga bloke ay simple: sila ay lokal sa block (mayroon si>

 "use strict"; if (someCondition) { foo(); // Works just fine function foo() { } } console.log(typeof foo); // "undefined" ('foo' is not in scope here // because it not in the same block) 

Pagpapahayag ng "anonymous" function

Ang pangalawang karaniwang anyo ay tinatawag na isang di-kila>

 var y = function () { console.log('y'); }; 

Tulad ng lahat ng mga expression, ito ay kinakalkula sa pag-abot sa sunud-sunod na pagpapatupad ng code.

Sa ES5, ang function na nilikha ay wa>y . Isang bagay na tulad nito ang nangyayari kapag ang function ay ang halaga ng initializer ng ari-arian. (Para sa karagdagang impormasyon tungkol sa kung kailan ito nangyayari at tungkol sa mga patakaran, hanapin ang SetFunctionName sa detalye - lumilitaw ito sa lahat ng dako.)

Pinangalanang function Named

Ang ikatlong form ay isang expression na may pinangalanan function ("NFE"):

 var z = function w() { console.log('zw') }; 

Ang function na lumilikha nito ay may sariling pangalan (sa kasong ito, w ). Tulad ng lahat ng mga expression, ito ay sinusuri kapag ito ay nakakamit sa sunud-sunod na pagpapatupad ng code. Ang pangalan ng pag-andar ay hindi idinagdag sa lugar kung saan lumilitaw ang expression; ang pangalan ay nasa saklaw ng pag-andar mismo:

 var z = function w() { console.log(typeof w); // "function" }; console.log(typeof w); // "undefined" 

Pakitandaan na ang mga NFE ay madalas na pinagmumulan ng mga error para sa pagpapatupad ng JavaScript. Halimbawa, ang IE8 at ang mga naunang bersyon ay humahawak ng lubos na mali sa NFE, na lumilikha ng dalawang iba't ibang mga pag-andar sa dalawang magkakaibang punto sa oras. Ang mga unang bersyon ng Safari ay nagkaroon din ng mga problema. Ang mabuting balita ay ang kasalukuyang bersyon ng mga browser (IE9 at mas mataas, ang kasalukuyang Safari), hindi na umiiral ang mga problemang iyon. (Subalit sa kasamaang-palad, sa panahon ng pagsulat na ito, IE8 ay pa rin ang malawak na ginagamit, at sa gayon ang paggamit ng NFE na may code para sa Internet sa kabuuan ay pa rin ang problema.)

Access Function Initializer (ES5 +)

Minsan ang mga pag-andar ay maaaring tumagos sa hindi napapansin; ano ang tungkol sa pag-andar ng pag-access Narito ang isang halimbawa:

 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" 

Pakitandaan na kapag ginamit ko ang function, hindi ko ginamit () ! Ito ay dahil ito ay isang access function para sa isang ari-arian. Nakukuha namin at itinakda ang ari-arian sa karaniwang paraan, ngunit sa likod ng mga eksena isang function ay tinatawag na.

Maaari ka ring lumikha ng mga function ng pag-access gamit ang Object.defineProperty , Object.defineProperties at ang mas maliit na kila>Object.create argument.

Pag-andar ng pag-andar ng arrow (ES2015 +)

Dinadala sa amin ng ES2015 ang function ng arrow. Narito ang isang halimbawa:

 var a = [1, 2, 3]; var b = a.map(n => n * 2); console.log(b.join(", ")); // 2, 4, 6 

Tingnan kung ano ang n => n * 2 ay nakatago sa map() tawag? Ito ay isang function.

Ang i>

  1. Wala si>this . Sa halip, isinasara nila this kontekstong ito kung saan tinukoy ang mga ito. (Ang mga ito ay malapit rin sa mga arguments at, kung naaangkop, super .) Nangangahulugan ito na this nasa kanila tulad this , kung saan nila>

  2. Tulad ng nabanggit mo sa itaas, hindi mo ginagamit ang function keyword; sa halip, ginagamit mo => .

Halimbawa n => n * 2 itaas ay isa sa kani>

 var a = [1, 2, 3]; var b = a.map((n, i) => n * i); console.log(b.join(", ")); // 0, 2, 6 

(Tandaan, ang Array#map pumasa sa rekord bi>

Sa parehong mga kaso, ang function na katawan ay isang pagpapahayag lamang; ang halaga ng pagbabalik ng function ay awtomatikong magiging resulta ng ekspresyong ito (hindi ka gumagamit ng isang malinaw na return ).

Kung gagawin mo ang higit pa sa isang expression, gamitin {} at isang malinaw na return (kung kai>

 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)); 

Ang isang bersyon na wa>{... } ay tinatawag na isang function na arrow na may isang katawan ng pagpapahayag o isang maikling katawan. (Gayundin: Mabilis na pag-andar ng arrow.) Ang function na may {... } pagtukoy sa katawan ay ang pag-andar ng arrow na may katawan ng function. (Gayundin: ang verb na arrow function.)

Pamamaraan deklarasyon sa object initializer (ES2015 +)

Ang ES2015 ay nagbibigay-daan para sa isang mas maikling form ng deklarasyon ng ari-arian na tumutukoy sa isang function na tinatawag na kahulugan ng paraan; mukhang ganito:

 var o = { foo() { } }; 

halos katumbas sa ES5 at mas naunang mga bersyon:

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

Ang pagkakaiba (maliban sa pagkalagot) ay ang paraan ng paggamit ng super , ngunit ang pag-andar ay hindi maaaring. Kaya, halimbawa, kung mayroon kang isang bagay na tinukoy (sabihin) valueOf gamit ang syntax ng isang paraan, maaari itong gumamit ng super.valueOf() upang makuha ang halaga ng Object.prototype.valueOf na dapat ibalik (bago ang paggawa ng isang bagay ibang bagay dito), samanta>Object.prototype.valueOf.call(this) gumawa Object.prototype.valueOf.call(this) .

Nangangahulugan din ito na ang pamamaraan ay may reference sa object na kung saan ito ay tinukoy, samakatuwid, kung ang bagay na ito ay pansamanta>Object.assign bi>super ).

Mga tagatukoy ng constructor at pamamaraan sa class (ES2015 +)

Nagbibigay sa amin ang ES2015 ng class syntax, kabi>

 class Person { constructor(firstName, lastName) { this.firstName = firstName; this.lastName = lastName; } getFullName() { return this.firstName + " " + this.lastName; } } 

Sa itaas ay dalawang function declarations: isa para sa getFullName , na kung saan ay pinangalanang Person , at getFullName para sa getFullName , na kung saan ay isang function na nakatalaga sa Person.prototype .

574
04 марта '14 в 16:35 2014-03-04 16:35 Sagot ay ibinigay ni TJ Crowder Marso 04 '14 sa 16:35 2014-03-04 16:35

Sa pagsasalita ng pandaigdigang konteksto, pareho ang mga pahayag ng var at FunctionDeclaration sa dulo ay lumikha ng isang di-mabubura na ari-arian para sa pandaigdigang bagay, ngunit ang halaga ng kapwa ay maaaring mapapatungan.

Ang banayad na pagkakaiba sa pagitan ng dalawang paraan ay kapag nagsimula ang proseso ng Variable Instantiation (bago ang aktwal na pagpapatupad ng code), ang lahat ng mga tagapagpakilala na ipinahayag na may var ay pinasimulan ng hindi undefined , at ang mga ginagamit ng FunctionDeclaration ay makukuha mula ngayon, halimbawa:

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

Ang pagtatalaga ng FunctionExpression ng bar ay ginagawa bago ang pagpapatupad.

Ang global na ari-arian na nilikha ng FunctionDeclaration ay maaaring mapapatungan nang wa>

  function test () {} test = null; 

Ang isa pang malinaw na kaibahan sa pagitan ng iyong dalawang halimbawa ay ang unang pag-andar ay wa>

Tungkol sa iyong na-edit na unang halimbawa ( foo = function() { alert('hello!'); }; ), Ito ay isang hindi naipahayag na gawain, masidhing inirerekumenda ko na lagi mong gamitin ang var keyword.

Kapag nakatalaga nang wa>var operator, kung ang reference identifier ay hindi matatagpuan sa saklaw ng saklaw, ito ay magiging isang naaalis na ari-arian ng pandaigdigang bagay.

Bi>ReferenceError sa ECMAScript 5 sa Mahigpit na Mode .

Dapat basahin ang:

Tandaan : Ang sagot na ito ay pinagsama mula sa isa pang tanong , kung saan ang pangunahing pag-aalin>FunctionDeclaration ay hindi mapapatungan, na hindi ito ang kaso.

137
08 авг. ang sagot ay ibinigay ng CMS 08 aug. 2010-08-08 22:32 '10 sa 10:32 2010-08-08 22:32

Ang dalawang snippet ng code na iyong inilalagay doon ay magkakaroon ng parehong para sa halos lahat ng mga layunin.

Gayunpaman, ang pagkakaiba sa pag-uugali ay na sa unang opsyon ( var functionOne = function() {} ) ang function na ito ay maaaring tawagin lamang matapos ang puntong ito sa code.

Sa ikalawang variant ( function functionTwo() ), ang function ay magagamit para sa code na naisakatuparan sa itaas, kung saan ang function ay ipinahayag.

Ito ay dahil sa ang katunayan na sa unang variant ang function ay nakatalaga sa variable foo sa run time. Sa ikalawang function, ang tagatukoy na ito ay itinalaga sa foo panahon ng pag-parse.

Karagdagang teknikal na impormasyon

Ang JavaScript ay may tatlong paraan upang tukuyin ang mga function.

  • Sa iyong unang snippet, ipinapakita ang function na expression. Ito ay dahil sa paggamit ng "function" na operator upang lumikha ng isang function - ang resulta ng operator na ito ay maaaring naka-imbak sa anumang variable o bagay. Ang function expression ay napakalakas. Ang isang function na expression ay madalas na tinatawag na isang "hindi kila>
  • Ang pangalawang halimbawa ay isang deklarasyon ng function. . Upang lumikha ng isang function, gamitin ang "function" operator. Ang pag-andar ay ibinibigay sa panahon ng pag-parse at maaaring tawagin kahit saan sa lugar na ito. Maaari mo itong i-save sa ibang pagkakataon sa isang variable o bagay.
  • Ang ikatlong paraan upang tukuyin ang isang function ay ang "Function ()" na tagapagbuo, na hindi ipinapakita sa orihinal na mensahe. Hindi inirerekumenda na gamitin ito, dahil gumagana ito sa parehong paraan tulad ng eval() , na may sariling mga problema.
115
20 апр. Ang sagot ay ibinigay ng thomasrutter Abril 20 2010-04-20 07:54 '10 sa 7:54 2010-04-20 07:54

Sagot ni Greg ang pinakamahusay na paliwanag

 functionTwo(); function functionTwo() { } 

Bakit wa> Lagi kaming itinuturo na ang mga expression ay pinaandar mula sa itaas hanggang sa ibaba (??)

Dahil:

Ang mga deklarasyon ng function at variable declarations ay laging inililipat ( hoisted ) invisibly sa tuktok ng kani>ben cherry

Nangangahulugan ito na ang gayong code:

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

Mangyaring tandaan na ang bahagi ng pagtatalaga ng mga deklarasyon ay hindi naitataas. Tanging ang pangalan ay nakataas.

Ngunit sa kaso ng mga deklarasyon ng pag-andar, ang katawan ng buong tungkulin ay itataas din:

 functionTwo(); --------------- function functionTwo() { | is actually | }; function functionTwo() { | interpreted |--> } | like | functionTwo(); --------------- 
96
09 авг. ang sagot ay ibinigay simple_human 09 aug. 2014-08-09 05:45 '14 sa 5:45 ng umaga 2014-08-09 05:45

Naisip ng ibang mga komentarista na ang pagkakaiba ng semantiko sa pagitan ng dalawang opsyon na nakalista sa itaas. Gusto kong ituro ang isang istilong pagkakaiba: ang pagkakaiba lamang ng "patutunguhan" ay maaaring magtatag ng ari-arian ng isa pang bagay.

Ako ay madalas na gumawa ng mga module ng JavaScript na may ganitong pattern:

 (function(){ var exports = {}; function privateUtil() { ... } exports.publicUtil = function() { ... }; return exports; })(); 

Gamit ang template na ito, gagamitin ng iyong mga pampublikong function ang patutunguhan, habang gagamitin ang iyong mga pribadong pag-andar sa ad.

(Tandaan din na ang takdang-aralin ay dapat maglaman ng isang tuldok-tuldok pagkatapos ng pagtuturo, samanta>

87
03 марта '11 в 22:19 2011-03-03 22:19 sumagot kay Sean McMillan noong Marso 03 '11 sa 22:19 2011-03-03 22:19

Ang isang paglalarawan ng kung kailan ito ay mas mahusay na gamitin ang unang paraan para sa ikalawa ay kapag kai>

Sa

 if (condition){ function myfunction(){ // Some code } } 

ang kahulugan na myfunction babaguhin ang anumang naunang kahulugan, dahil ito ay isasagawa sa panahon ng pag-parse.

Habang

 if (condition){ var myfunction = function (){ // Some code } } 

ay ang tamang trabaho ng pagtukoy ng myfunction lamang kapag ang condition ay ipapatupad.

73
29 марта '13 в 16:26 2013-03-29 16:26 Sagot na ibinigay ng Mbengue Assane noong Marso 29 '13 sa 16:26 2013-03-29 16:26

Ang isang mahalagang dahilan ay ang pagdaragdag ng isa at isa lamang na variable bi>

 var MyNamespace = {} MyNamespace.foo= function() { } 

o

 var MyNamespace = { foo: function() { }, ... } 

Maraming mga pamamaraan para sa namespace. Ito ay nagiging mas mahalaga sa maraming JavaScript module na magagamit.

Tingnan din. Paano ipahayag ang mga namespace sa javascript?

59
08 авг. ang sagot ay ibinigay ni Rob 08 aug. 2010-08-08 22:44 '10 at 10:44 PM 2010-08-08 22:44

Hoisting ay isang pagkilos ng interpreter ng JavaScript para sa paglipat ng lahat ng mga deklarasyon ng mga variable at pag-andar sa simula ng kasalukuyang saklaw.