J'ai récemment commencé à maintenir le code JavaScript de quelqu'un d'autre. Je corrige des bugs, j'ajoute des fonctionnalités et j'essaie également de ranger le code et de le rendre plus cohérent.
Le développeur précédent a utilisé deux façons de déclarer des fonctions et je ne peux pas déterminer s'il y a une raison ou non.
Les deux manières sont:
var functionOne = function() {
// Some code
};
function functionTwo() {
// Some code
}
Quelles sont les raisons d'utiliser ces deux méthodes différentes et quels sont les avantages et les inconvénients de chacune? Y a-t-il quelque chose qui peut être fait avec une méthode qui ne peut pas être fait avec l'autre?
javascript
function
syntax
idioms
Richard Garside
la source
la source
var a = 1; var b = 2;
devientvar a; var b; a = 1; b = 2
. Ainsi, lorsque vous déclarez functionOne, il est déclaré mais sa valeur n'est pas définie immédiatement. Alors que functionTwo n'est qu'une déclaration, elle est placée en haut de la portée. # 2 functionTwo vous permet d'accéder à la propriété name et cela aide beaucoup lorsque vous essayez de déboguer quelque chose.function f(){}
vsvar f = function(){};
.Réponses:
La différence est qu'il
functionOne
s'agit d'une expression de fonction et donc uniquement définie lorsque cette ligne est atteinte, alors qu'ilfunctionTwo
s'agit d'une déclaration de fonction et est définie dès que sa fonction ou son script environnant est exécuté (en raison d'un hissage ).Par exemple, une expression de fonction:
Et, une déclaration de fonction:
Historiquement, les déclarations de fonctions définies dans les blocs étaient gérées de manière incohérente entre les navigateurs. Le mode strict (introduit dans ES5) a résolu ce problème en délimitant les déclarations de fonction dans leur bloc englobant.
la source
functionOne
est simplement une variable à laquelle est affectée une fonction anonyme, alors qu'ilfunctionTwo
s'agit en fait d'une fonction nommée. Faites appel.toString()
aux deux pour voir la différence. Cela est important dans certains cas où vous souhaitez obtenir le nom d'une fonction par programme.function expression
le second est unfunction declaration
. Vous pouvez en savoir plus sur le sujet ici: javascriptweblog.wordpress.com/2010/07/06/…Je veux d'abord corriger Greg:
function abc(){}
est égalementabc
délimité - le nom est défini dans la portée où cette définition est rencontrée. Exemple:Deuxièmement, il est possible de combiner les deux styles:
xyz
va être défini comme d'habitude,abc
n'est pas défini dans tous les navigateurs, mais Internet Explorer - ne comptez pas sur sa définition. Mais il sera défini à l'intérieur de son corps:Si vous souhaitez alias des fonctions sur tous les navigateurs, utilisez ce type de déclaration:
Dans ce cas, les deux
xyz
etabc
sont des alias du même objet:Une raison impérieuse d'utiliser le style combiné est l'attribut "nom" des objets fonction ( non pris en charge par Internet Explorer ). Fondamentalement, lorsque vous définissez une fonction comme
son nom est automatiquement attribué. Mais quand vous le définissez comme
son nom est vide - nous avons créé une fonction anonyme et l'avons assignée à une variable.
Une autre bonne raison d'utiliser le style combiné est d'utiliser un nom interne court pour se référer à lui-même, tout en fournissant un nom long et non conflictuel aux utilisateurs externes:
Dans l'exemple ci-dessus, nous pouvons faire de même avec un nom externe, mais ce sera trop lourd (et plus lent).
(Une autre façon de se référer à lui-même est d'utiliser
arguments.callee
, qui est encore relativement longue et non prise en charge en mode strict.)Au fond, JavaScript traite les deux déclarations différemment. Ceci est une déclaration de fonction:
abc
ici est défini partout dans le périmètre actuel:En outre, il a été hissé à travers une
return
déclaration:Il s'agit d'une expression de fonction:
xyz
ici est défini à partir du point d'affectation:Déclaration de fonction vs expression de fonction est la vraie raison pour laquelle il y a une différence démontrée par Greg.
Fait amusant:
Personnellement, je préfère la déclaration "expression de fonction" car de cette façon je peux contrôler la visibilité. Quand je définis la fonction comme
Je sais que j'ai défini la fonction localement. Quand je définis la fonction comme
Je sais que je l'ai défini globalement à condition de ne le définir
abc
nulle part dans la chaîne des étendues. Ce style de définition est résistant même lorsqu'il est utilisé à l'intérieureval()
. Bien que la définitiondépend du contexte et peut vous laisser deviner où il est réellement défini, en particulier dans le cas de
eval()
- la réponse est: cela dépend du navigateur.la source
var abc = function(){}; console.log(abc.name);
ne produit""
plus, mais à la"abc"
place.Voici le récapitulatif des formulaires standard qui créent des fonctions: (Initialement écrit pour une autre question, mais adapté après avoir été déplacé dans la question canonique.)
Termes:
La liste rapide:
Déclaration de fonction
function
Expression "anonyme" (qui malgré le terme, crée parfois des fonctions avec des noms)function
Expression nomméeInitialiseur de fonction d'accesseur (ES5 +)
Expression de fonction de flèche (ES2015 +) (qui, comme les expressions de fonction anonymes, n'implique pas de nom explicite et peut néanmoins créer des fonctions avec des noms)
Déclaration de méthode dans l'initialiseur d'objet (ES2015 +)
Déclarations de constructeur et de méthode dans
class
(ES2015 +)Déclaration de fonction
Le premier formulaire est une déclaration de fonction , qui ressemble à ceci:
Une déclaration de fonction est une déclaration ; ce n'est pas une déclaration ou une expression. En tant que tel, vous ne le suivez pas avec un
;
(bien que cela soit inoffensif).Une déclaration de fonction est traitée lorsque l'exécution entre dans le contexte dans lequel elle apparaît, avant l' exécution de tout code étape par étape. La fonction qu'elle crée reçoit un nom propre (
x
dans l'exemple ci-dessus), et ce nom est placé dans la portée dans laquelle la déclaration apparaît.Parce qu'il est traité avant tout code étape par étape dans le même contexte, vous pouvez faire des choses comme ceci:
Jusqu'à ES2015, la spécification ne couvre pas ce que l' intérieur d' une structure de contrôle comme un moteur JavaScript doit faire si vous mettez une déclaration de fonction
try
,if
,switch
,while
, etc., comme ceci:Et comme ils sont traités avant l' exécution du code étape par étape, il est difficile de savoir quoi faire lorsqu'ils sont dans une structure de contrôle.
Bien que cela n'ait pas été spécifié avant ES2015, c'était une extension autorisée pour prendre en charge les déclarations de fonction dans les blocs. Malheureusement (et inévitablement), différents moteurs ont fait des choses différentes.
Depuis ES2015, la spécification indique ce qu'il faut faire. En fait, cela donne trois choses distinctes à faire:
Les règles pour les modes lâches sont délicates, mais en mode strict , les déclarations de fonctions dans les blocs sont faciles: elles sont locales au bloc (elles ont une portée de bloc , qui est également nouvelle dans ES2015), et elles sont hissées vers le haut du bloc. Donc:
function
Expression "anonyme"La deuxième forme courante est appelée une expression de fonction anonyme :
Comme toutes les expressions, il est évalué lorsqu'il est atteint lors de l'exécution pas à pas du code.
Dans ES5, la fonction ainsi créée n'a pas de nom (elle est anonyme). Dans ES2015, la fonction se voit attribuer un nom si possible en le déduisant du contexte. Dans l'exemple ci-dessus, le nom serait
y
. Quelque chose de similaire est fait lorsque la fonction est la valeur d'un initialiseur de propriété. (Pour plus de détails sur le moment où cela se produit et les règles, recherchezSetFunctionName
dans la spécification - elle apparaît partout .)function
Expression nomméeLa troisième forme est une expression de fonction nommée ("NFE"):
La fonction ainsi créée porte un nom propre (
w
dans ce cas). Comme toutes les expressions, cela est évalué lorsqu'il est atteint lors de l'exécution pas à pas du code. Le nom de la fonction n'est pas ajouté à la portée dans laquelle l'expression apparaît; le nom est dans la portée de la fonction elle-même:Notez que les NFE ont souvent été une source de bogues pour les implémentations JavaScript. IE8 et les versions antérieures, par exemple, gèrent les NFE de manière complètement incorrecte , créant deux fonctions différentes à deux moments différents. Les premières versions de Safari avaient également des problèmes. La bonne nouvelle est que les versions actuelles des navigateurs (IE9 et plus, Safari actuel) n'ont plus ces problèmes. (Mais à ce jour, malheureusement, IE8 reste largement utilisé, et donc l'utilisation d'ENF avec du code pour le Web en général reste problématique.)
Initialiseur de fonction d'accesseur (ES5 +)
Parfois, les fonctions peuvent passer inaperçues en grande partie; c'est le cas des fonctions d'accesseur . Voici un exemple:
Notez que lorsque j'ai utilisé la fonction, je ne l'ai pas utilisée
()
! C'est parce que c'est une fonction d'accesseur pour une propriété. Nous obtenons et définissons la propriété de la manière normale, mais en arrière-plan, la fonction est appelée.Vous pouvez également créer des accesseurs fonctions avec
Object.defineProperty
,Object.defineProperties
et le second argument moins connu pourObject.create
.Expression de la fonction flèche (ES2015 +)
ES2015 nous apporte la fonction flèche . Voici un exemple:
Vous voyez cette
n => n * 2
chose qui se cache dans l'map()
appel? C'est une fonction.Quelques choses sur les fonctions fléchées:
Ils n'ont pas les leurs
this
. Au lieu de cela, ils près sur lethis
du contexte dans lequel elles sont définies. (Ils se ferment égalementarguments
et, le cas échéant,.super
) Cela signifie que l'this
intérieur d'eux est le même que l'this
endroit où ils ont été créés et ne peut pas être modifié.Comme vous l'avez remarqué avec ce qui précède, vous n'utilisez pas le mot-clé
function
; à la place, vous utilisez=>
.L'
n => n * 2
exemple ci-dessus en est une forme. Si vous avez plusieurs arguments pour passer la fonction, vous utilisez des parens:(N'oubliez pas que
Array#map
passe l'entrée comme premier argument et l'index comme deuxième.)Dans les deux cas, le corps de la fonction n'est qu'une expression; la valeur de retour de la fonction sera automatiquement le résultat de cette expression (vous n'utilisez pas d'explicite
return
).Si vous faites plus qu'une simple expression, utilisez
{}
et une explicitereturn
(si vous devez retourner une valeur), comme d'habitude:La version sans
{ ... }
est appelée fonction de flèche avec un corps d'expression ou un corps concis . (Aussi: Une fonction de flèche concise .) Celui qui{ ... }
définit le corps est une fonction de flèche avec un corps de fonction . (Aussi: Une fonction de flèche verbeuse .)Déclaration de méthode dans l'initialiseur d'objet (ES2015 +)
ES2015 permet une forme plus courte de déclaration d'une propriété qui fait référence à une fonction appelée définition de méthode ; cela ressemble à ceci:
le quasi-équivalent dans ES5 et les versions antérieures serait:
la différence (autre que la verbosité) est qu'une méthode peut utiliser
super
, mais pas une fonction. Ainsi, par exemple, si vous aviez un objet qui définissait (disons) envalueOf
utilisant la syntaxe de la méthode, il pourrait utilisersuper.valueOf()
pour obtenir la valeurObject.prototype.valueOf
serait retourné (avant de faire probablement autre chose avec lui), alors que la version ES5 devrait le faire à laObject.prototype.valueOf.call(this)
place.Cela signifie également que la méthode a une référence à l'objet sur lequel elle a été définie, donc si cet objet est temporaire (par exemple, vous le transmettez
Object.assign
comme l'un des objets source), la syntaxe de la méthode pourrait signifier que l'objet est conservé en mémoire alors qu'il aurait pu être récupéré (si le moteur JavaScript ne détecte pas cette situation et ne la gère si aucune des méthodes ne l'utilisesuper
).Déclarations de constructeur et de méthode dans
class
(ES2015 +)ES2015 nous apporte la
class
syntaxe, y compris les constructeurs et méthodes déclarés:Il y a deux déclarations de fonction ci-dessus: une pour le constructeur, qui obtient le nom
Person
, et une pourgetFullName
, qui est une fonction affectée àPerson.prototype
.la source
w
est simplement ignoré?En parlant du contexte global, à la fois, l'
var
instruction et unFunctionDeclaration
à la fin créeront une propriété non supprimable sur l'objet global, mais la valeur des deux peut être écrasée .La différence subtile entre les deux façons est que lorsque le processus d' instanciation variable s'exécute (avant l'exécution du code réel) tous les identifiants déclarés avec
var
seront initialisés avecundefined
, et ceux utilisés par lesFunctionDeclaration
seront disponibles depuis ce moment, par exemple:L'affectation du
bar
FunctionExpression
se déroule jusqu'à l'exécution.Une propriété globale créée par un
FunctionDeclaration
peut être remplacée sans aucun problème comme une valeur de variable, par exemple:Une autre différence évidente entre vos deux exemples est que la première fonction n'a pas de nom, mais la seconde l'a, ce qui peut être très utile lors du débogage (c'est-à-dire inspecter une pile d'appels).
À propos de votre premier exemple modifié (
foo = function() { alert('hello!'); };
), il s'agit d'une affectation non déclarée, je vous encourage vivement à toujours utiliser levar
mot - clé.Avec une mission, sans
var
instruction, si l'identifiant référencé ne se trouve pas dans la chaîne de portée, il deviendra une propriété supprimable de l'objet global.En outre, les affectations non déclarées jettent un
ReferenceError
ECMAScript 5 en mode strict .À lire absolument:
Remarque : Cette réponse a été fusionnée à partir d' une autre question , dans laquelle le doute majeur et l'idée fausse du PO étaient que les identifiants déclarés avec un
FunctionDeclaration
ne pouvaient pas être remplacés, ce qui n'est pas le cas.la source
Les deux extraits de code que vous y avez publiés se comporteront, à presque toutes les fins, de la même manière.
Cependant, la différence de comportement est qu'avec la première variante (
var functionOne = function() {}
), cette fonction ne peut être appelée qu'après ce point dans le code.Avec la deuxième variante (
function functionTwo()
), la fonction est disponible pour le code qui s'exécute au-dessus de l'endroit où la fonction est déclarée.En effet, avec la première variante, la fonction est affectée à la variable
foo
au moment de l'exécution. Dans le second, la fonction est affectée à cet identifiantfoo
, au moment de l'analyse.Plus d'informations techniques
JavaScript a trois façons de définir les fonctions.
eval()
, ce qui a ses problèmes.la source
Une meilleure explication à la réponse de Greg
Pourquoi pas d'erreur? On nous a toujours appris que les expressions sont exécutées de haut en bas (??)
Parce que:
Cela signifie que le code comme celui-ci:
Notez que la partie affectation des déclarations n'a pas été hissée. Seul le nom est hissé.
Mais dans le cas des déclarations de fonctions, tout le corps de la fonction sera également hissé :
la source
D'autres commentateurs ont déjà couvert la différence sémantique des deux variantes ci-dessus. Je voulais noter une différence stylistique: seule la variation "affectation" peut définir une propriété d'un autre objet.
Je construis souvent des modules JavaScript avec un modèle comme celui-ci:
Avec ce modèle, vos fonctions publiques utiliseront toutes l'affectation, tandis que vos fonctions privées utiliseront la déclaration.
(Notez également que l'affectation doit nécessiter un point-virgule après l'instruction, tandis que la déclaration l'interdit.)
la source
var foo = function(){...}
syntaxe même pour les variables privées.function window.onload() {}
était une chose.)Une illustration de quand préférer la première méthode à la seconde est quand vous devez éviter de remplacer les définitions précédentes d'une fonction.
Avec
, cette définition de
myfunction
remplacera toute définition précédente, car elle sera effectuée au moment de l'analyse.Tandis que
fait le travail correct de définir
myfunction
uniquement quandcondition
est atteint.la source
var myFunc = null;
dehors d'une boucle, ou en dehors d'un bloc if / elseif / else. Vous pouvez ensuite affecter conditionnellement différentes fonctions à la même variable. Dans JS, il est préférable d'assigner une valeur manquante à null, puis à undefined. Par conséquent, vous devez d'abord déclarer myFunction comme nulle, puis l'affecter ultérieurement, conditionnellement.Une raison importante est d'ajouter une et une seule variable comme "racine" de votre espace de noms ...
ou
Il existe de nombreuses techniques d'espacement de noms. C'est devenu plus important avec la pléthore de modules JavaScript disponibles.
Voir aussi Comment déclarer un espace de noms en JavaScript?
la source
Le levage est l'action de l'interpréteur JavaScript de déplacer toutes les déclarations de variables et de fonctions en haut de la portée actuelle.
Cependant, seules les déclarations réelles sont hissées. en laissant les affectations là où elles sont.
Variable
Javascript est appelé langage peu typé. Ce qui signifie que les variables Javascript peuvent contenir la valeur de n'importe quel type de données . Javascript prend automatiquement en charge la modification du type de variable en fonction de la valeur / du littéral fourni lors de l'exécution.
Une fonction
La valeur de retour par défaut de la fonction est « non définie », la valeur par défaut de la déclaration de variable est également «non définie»
Déclaration de fonction
Expression de fonction
Fonction affectée à la variable Exemple:
javascript interprété comme
Vous pouvez vérifier la déclaration de fonction, le test d'expression sur différents navigateurs en utilisant
jsperf Test Runner
ES5 Constructor Function Classes : objets de fonction créés à l'aide de Function.prototype.bind
JavaScript traite les fonctions comme des objets de première classe. En tant qu'objet, vous pouvez affecter des propriétés à une fonction.
ES6 a introduit la fonction Flèche : une expression de fonction Flèche a une syntaxe plus courte, elle est mieux adaptée aux fonctions non-méthode et ne peut pas être utilisée comme constructeur.
la source
J'ajoute ma propre réponse juste parce que tout le monde a soigneusement couvert la partie de levage.
Je me demande depuis longtemps quel est le meilleur chemin, et grâce à http://jsperf.com maintenant je sais :)
Les déclarations de fonctions sont plus rapides, et c'est ce qui compte vraiment dans le développement Web, non? ;)
la source
Une déclaration de fonction et une expression de fonction affectées à une variable se comportent de la même manière une fois la liaison établie.
Il existe cependant une différence quant à la manière et au moment où l'objet fonction est réellement associé à sa variable. Cette différence est due au mécanisme appelé levage variable en JavaScript.
Fondamentalement, toutes les déclarations de fonctions et les déclarations de variables sont hissées au sommet de la fonction dans laquelle la déclaration se produit (c'est pourquoi nous disons que JavaScript a une portée de fonction ).
Lorsqu'une déclaration de fonction est hissée, le corps de la fonction "suit", donc lorsque le corps de la fonction est évalué, la variable sera immédiatement liée à un objet fonction.
Lorsqu'une déclaration de variable est hissée, l'initialisation ne suit pas , mais est "laissée pour compte". La variable est initialisée
undefined
au début du corps de la fonction et se verra attribuer une valeur à son emplacement d'origine dans le code. (En fait, une valeur lui sera attribuée à chaque emplacement où se produit la déclaration d'une variable du même nom.)L'ordre de levage est également important: les déclarations de fonctions ont priorité sur les déclarations de variables portant le même nom et la dernière déclaration de fonctions a priorité sur les déclarations de fonctions précédentes portant le même nom.
Quelques exemples...
La variable
foo
est hissée en haut de la fonction, initialisée àundefined
, c'est-à-!foo
dire qu'elle esttrue
doncfoo
affectée10
. L'foo
extérieur debar
la portée de ne joue aucun rôle et reste intact.Les déclarations de fonctions ont priorité sur les déclarations de variables et la dernière déclaration de fonction "colle".
Dans cet exemple,
a
est initialisé avec l'objet fonction résultant de l'évaluation de la deuxième déclaration de fonction, puis est affecté4
.Ici, la déclaration de fonction est hissée en premier, déclarant et initialisant une variable
a
. Ensuite, cette variable est affectée10
. En d'autres termes: l'affectation n'est pas affectée à la variable externea
.la source
Le premier exemple est une déclaration de fonction:
Le deuxième exemple est une expression de fonction:
La principale différence est de savoir comment ils sont hissés (levés et déclarés). Dans le premier exemple, la déclaration de fonction entière est hissée. Dans le deuxième exemple, seul le var 'abc' est hissé, sa valeur (la fonction) sera indéfinie et la fonction elle-même reste à la position où elle est déclarée.
Pour le dire simplement:
Pour en savoir plus sur ce sujet, je vous recommande fortement ce lien
la source
En termes de coût de maintenance du code, les fonctions nommées sont plus préférables:
Je soupçonne que plus de PROS pour les fonctions nommées sont suivis. Et ce qui est répertorié comme un avantage des fonctions nommées est un inconvénient pour les fonctions anonymes.
Historiquement, les fonctions anonymes sont apparues à cause de l'incapacité de JavaScript en tant que langage à répertorier les membres avec des fonctions nommées:
la source
En termes informatiques, nous parlons de fonctions anonymes et de fonctions nommées. Je pense que la différence la plus importante est qu'une fonction anonyme n'est pas liée à un nom, d'où le nom de fonction anonyme. En JavaScript, il s'agit d'un objet de première classe déclaré dynamiquement lors de l'exécution.
Pour plus d'informations sur les fonctions anonymes et le calcul lambda, Wikipedia est un bon début ( http://en.wikipedia.org/wiki/Anonymous_function ).
la source
J'utilise l'approche variable dans mon code pour une raison très spécifique, dont la théorie a été abordée de manière abstraite ci-dessus, mais un exemple pourrait aider certaines personnes comme moi, avec une expertise JavaScript limitée.
J'ai du code que je dois exécuter avec 160 marques conçues indépendamment. La plupart du code se trouve dans des fichiers partagés, mais les éléments spécifiques à la marque se trouvent dans un fichier distinct, un pour chaque marque.
Certaines marques nécessitent des fonctions spécifiques, d'autres non. Parfois, je dois ajouter de nouvelles fonctions pour faire de nouvelles choses spécifiques à la marque. Je suis heureux de changer le codage partagé, mais je ne veux pas avoir à changer les 160 ensembles de fichiers de marque.
En utilisant la syntaxe des variables, je peux déclarer la variable (un pointeur de fonction essentiellement) dans le code partagé et soit attribuer une fonction de remplacement triviale, soit définir sur null.
Le ou les deux brandings qui ont besoin d'une implémentation spécifique de la fonction peuvent alors définir leur version de la fonction et l'affecter à la variable s'ils le souhaitent, et les autres ne font rien. Je peux tester une fonction nulle avant de l'exécuter dans le code partagé.
D'après les commentaires des gens ci-dessus, je suppose qu'il est également possible de redéfinir une fonction statique, mais je pense que la solution variable est agréable et claire.
la source
La réponse de Greg est assez bonne, mais je voudrais quand même ajouter quelque chose que j'ai appris tout à l'heure en regardant les vidéos de Douglas Crockford .
Expression de fonction:
Énoncé de fonction:
L'instruction de fonction n'est qu'un raccourci pour une
var
instruction avec unefunction
valeur.Donc
s'étend à
Qui s'étend encore à:
Et ils sont tous les deux hissés en haut du code.
la source
Il existe quatre comparaisons notables entre les deux différentes déclarations de fonctions énumérées ci-dessous.
Ce qui suit fonctionne car
function add()
est limité au bloc le plus proche:Ce qui suit ne fonctionne pas car la variable est appelée avant qu'une valeur de fonction ne soit affectée à la variable
add
.Le code ci-dessus a une fonctionnalité identique au code ci-dessous. Notez que l'affectation explicite
add = undefined
est superflue car simplement fairevar add;
est exactement la même chose quevar add=undefined
.Ce qui suit ne fonctionne pas car le
var add=
super-ensemencement lefunction add()
.Le nom d'une fonction
function thefuncname(){}
est thefuncname quand elle est déclarée de cette façon.Sinon, si une fonction est déclarée comme
function(){}
, la fonction .name est la première variable utilisée pour stocker la fonction.S'il n'y a pas de variables définies pour la fonction, alors le nom des fonctions est la chaîne vide (
""
).Enfin, alors que la variable à laquelle la fonction est affectée définit initialement le nom, les variables successives définies sur la fonction ne changent pas le nom.
Dans le V8 de Google et Spidermonkey de Firefox, il pourrait y avoir quelques différences de compilation JIST en quelques microsecondes, mais en fin de compte, le résultat est exactement le même. Pour le prouver, examinons l'efficacité de JSPerf aux microbenchmarks en comparant la vitesse de deux extraits de code vierges. Les tests JSPerf se trouvent ici . Et, les tests jsben.ch se trouvent ici . Comme vous pouvez le voir, il y a une différence notable quand il ne devrait pas y en avoir. Si vous êtes vraiment un monstre de performance comme moi, cela vaut peut-être mieux que vous essayiez de réduire le nombre de variables et de fonctions dans la portée et surtout d'éliminer le polymorphisme (comme utiliser la même variable pour stocker deux types différents).
Lorsque vous utilisez le
var
mot clé pour déclarer une variable, vous pouvez ensuite réaffecter une valeur différente à la variable comme ceci.Cependant, lorsque nous utilisons l'instruction const, la référence de variable devient immuable. Cela signifie que nous ne pouvons pas affecter une nouvelle valeur à la variable. Veuillez noter, cependant, que cela ne rend pas le contenu de la variable immuable: si vous le faites
const arr = []
, vous pouvez toujours le fairearr[10] = "example"
. Faire seulement quelque chose commearr = "new value"
ouarr = []
lancerait une erreur comme vu ci-dessous.Fait intéressant, si nous déclarons la variable comme
function funcName(){}
, alors l'immuabilité de la variable est identique à la déclarer avecvar
.Quel est le "bloc le plus proche"
Le "bloc le plus proche" est la "fonction" la plus proche (y compris les fonctions asynchrones, les fonctions de générateur et les fonctions de générateur asynchrone). Cependant, il est intéressant de noter qu'un a
function functionName() {}
se comporte comme unvar functionName = function() {}
élément dans un bloc sans fermeture vis-à-vis des articles en dehors de ladite fermeture. Observer.var add=function(){}
function add(){}
if
,else
,for
,while
,try
/catch
/finally
,switch
,do
/while
,with
)var add=function()
function add()
la source
@EugeneLazutkin donne un exemple où il nomme une fonction assignée pour pouvoir l'utiliser
shortcut()
comme référence interne à lui-même. John Resig donne un autre exemple: copier une fonction récursive affectée à un autre objet dans son Learning Advanced Javascript didacticiel . Bien que l'attribution de fonctions aux propriétés ne soit pas strictement la question ici, je recommande d'essayer activement le didacticiel - exécutez le code en cliquant sur le bouton dans le coin supérieur droit et double-cliquez sur le code pour le modifier à votre guise.Exemples du tutoriel: appels récursifs dans
yell()
:Les tests échouent lorsque l'objet ninja d'origine est supprimé. (page 13)
Si vous nommez la fonction qui sera appelée récursivement, les tests réussiront. (page 14)
la source
Une autre différence qui n'est pas mentionnée dans les autres réponses est que si vous utilisez la fonction anonyme
et l'utiliser comme constructeur comme dans
alors
one.constructor.name
ne sera pas défini.Function.name
n'est pas standard mais est pris en charge par Firefox, Chrome, d'autres navigateurs dérivés de Webkit et IE 9+.Avec
il est possible de récupérer le nom du constructeur sous forme de chaîne avec
two.constructor.name
.la source
La première (fonction doSomething (x)) doit faire partie d'une notation d'objet.
Le second (
var doSomething = function(x){ alert(x);}
) crée simplement une fonction anonyme et l'affecte à une variable,doSomething
. Donc, doSomething () appellera la fonction.Vous voudrez peut-être savoir ce qu'une déclaration de fonction et une expression de fonction .
Une déclaration de fonction définit une variable de fonction nommée sans nécessiter d'affectation de variable. Les déclarations de fonctions se produisent en tant que constructions autonomes et ne peuvent pas être imbriquées dans des blocs non fonctionnels.
Dans la condition ci-dessus, le nom de la fonction est visible dans sa portée et la portée de son parent (sinon il serait inaccessible).
Et dans une expression de fonction
Une expression de fonction définit une fonction comme faisant partie d'une syntaxe d'expression plus large (généralement une affectation de variable). Les fonctions définies via des expressions de fonctions peuvent être nommées ou anonymes. Les expressions de fonction ne doivent pas commencer par «fonction».
la source
Je liste les différences ci-dessous:
Une déclaration de fonction peut être placée n'importe où dans le code. Même si elle est invoquée avant que la définition n'apparaisse dans le code, elle est exécutée lorsque la déclaration de fonction est validée en mémoire ou d'une manière telle qu'elle est hissée, avant que tout autre code de la page ne commence son exécution.
Jetez un œil à la fonction ci-dessous:
En effet, lors de l'exécution, il ressemble à: -
Une expression de fonction, si elle n'est pas définie avant de l'appeler, entraînera une erreur. Ici aussi, la définition de la fonction elle-même n'est pas déplacée vers le haut ou enregistrée dans la mémoire comme dans les déclarations de fonction. Mais la variable à laquelle nous attribuons la fonction est hissée et undefined lui est assigné.
Même fonction en utilisant des expressions de fonction:
En effet, lors de l'exécution, cela ressemble à:
Il n'est pas sûr d'écrire des déclarations de fonctions dans des blocs non fonctionnels comme si car elles ne seront pas accessibles.
L'expression de fonction nommée comme celle ci-dessous peut ne pas fonctionner dans les navigateurs Internet Explorer antérieurs à la version 9.
la source
Si vous utilisiez ces fonctions pour créer des objets, vous obtiendriez:
la source
console.log(objectOne.__proto__);
affiche "functionOne {}" dans ma console. Des idées sur la raison pour laquelle cela peut être le cas?À la lumière de l'argument "les fonctions nommées apparaissent dans les traces de pile", les moteurs JavaScript modernes sont en fait tout à fait capables de représenter des fonctions anonymes.
À ce jour, V8, SpiderMonkey, Chakra et Nitro se réfèrent toujours aux fonctions nommées par leurs noms. Ils se réfèrent presque toujours à une fonction anonyme par son identifiant si elle en possède une.
SpiderMonkey peut déterminer le nom d'une fonction anonyme renvoyée par une autre fonction. Le reste ne peut pas.
Si vous vouliez vraiment, vraiment que votre itérateur et vos rappels de succès apparaissent dans la trace, vous pouvez aussi les nommer ...
Mais pour la plupart, cela ne vaut pas la peine d'être souligné.
Harnais ( violon )
V8
SpiderMonkey
Chakra
Nitro
la source
En JavaScript, il existe deux façons de créer des fonctions:
Déclaration de fonction:
Ceci est très basique, explicite, utilisé dans de nombreuses langues et standard dans la famille de langues C. Nous avons déclaré qu'une fonction l'avait définie et exécutée en l'appelant.
Ce que vous devez savoir, c'est que les fonctions sont en fait des objets en JavaScript; en interne, nous avons créé un objet pour la fonction ci-dessus et lui avons donné un nom appelé fn ou la référence à l'objet est stockée dans fn. Les fonctions sont des objets en JavaScript; une instance de fonction est en fait une instance d'objet.
Expression de fonction:
JavaScript a des fonctions de première classe, c'est-à-dire créer une fonction et l'affecter à une variable comme vous créez une chaîne ou un nombre et l'affectez à une variable. Ici, la variable fn est affectée à une fonction. La raison de ce concept est que les fonctions sont des objets en JavaScript; fn pointe vers l'instance d'objet de la fonction ci-dessus. Nous avons initialisé une fonction et l'avons assignée à une variable. Il ne s'agit pas d'exécuter la fonction et d'attribuer le résultat.
Référence: syntaxe de déclaration de fonction JavaScript: var fn = function () {} vs function fn () {}
la source
var fn = function fn() {...}
,?Les deux sont des façons différentes de définir une fonction. La différence réside dans la façon dont le navigateur les interprète et les charge dans un contexte d'exécution.
Le premier cas est celui des expressions de fonction qui ne se chargent que lorsque l'interpréteur atteint cette ligne de code. Donc, si vous le faites comme suit, vous obtiendrez une erreur indiquant que functionOne n'est pas une fonction .
La raison en est que sur la première ligne aucune valeur n'est affectée à functionOne, et donc elle n'est pas définie. Nous essayons de l'appeler en tant que fonction, et donc nous obtenons une erreur.
Sur la deuxième ligne, nous attribuons la référence d'une fonction anonyme à functionOne.
Le deuxième cas est celui des déclarations de fonctions qui se chargent avant l'exécution de tout code. Donc, si vous aimez ce qui suit, vous n'obtiendrez aucune erreur lors du chargement de la déclaration avant l'exécution du code.
la source
À propos des performances:
De nouvelles versions de
V8
introduit plusieurs optimisations sous le capot et ainsi de suiteSpiderMonkey
.Il n'y a presque plus de différence entre expression et déclaration.
L'expression de la fonction semble être plus rapide maintenant.
Chrome 62.0.3202
FireFox 55
Chrome Canary 63.0.3225
Firefox Chrome Canary Chrome
la source
Ils sont assez similaires avec quelques petites différences, la première est une variable qui est affectée à une fonction anonyme (Déclaration de fonction) et la seconde est la manière normale de créer une fonction en JavaScript (Déclaration de fonction anonyme), les deux ont une utilisation, des inconvénients et des avantages :
1. Expression de fonction
Assigner une variable à une fonction, signifie pas de levage, comme nous savons que les fonctions JavaScript peuvent Hoist, cela signifie qu'elles peuvent être appelées avant d'être déclarées, tandis que les variables doivent être déclarées avant d'y accéder, ce qui signifie que dans ce cas, nous ne pouvons pas accéder à la fonction avant l'endroit où elle est déclarée, cela pourrait également être un moyen d'écrire vos fonctions, pour les fonctions qui renvoient une autre fonction, ce type de déclaration pourrait avoir du sens, également dans ECMA6 et ci-dessus, vous pouvez l'assigner à une fonction de flèche qui peut être utilisé pour appeler des fonctions anonymes, également cette façon de déclarer est une meilleure façon de créer des fonctions Constructor en JavaScript.
2. Déclaration de fonction
C'est la façon normale d'appeler une fonction en JavaScript, cette fonction peut être appelée avant même de la déclarer car en JavaScript toutes les fonctions sont hissées, mais si vous avez 'utiliser strict' cela ne sera pas Hoist comme prévu, c'est un bon moyen pour appeler toutes les fonctions normales qui ne sont pas grandes en lignes et ne sont pas non plus une fonction constructeur.
De plus, si vous avez besoin de plus d'informations sur le fonctionnement du levage en JavaScript, visitez le lien ci-dessous:
https://developer.mozilla.org/en-US/docs/Glossary/Hoisting
la source
...also this way of declaring is a better way to create Constructor functions in JavaScript
, veuillez élaborer, je suis curieux!Ce ne sont que deux façons possibles de déclarer des fonctions et, dans le second, vous pouvez utiliser la fonction avant la déclaration.
la source
new Function()
peut être utilisé pour passer le corps de la fonction dans une chaîne. Et donc cela peut être utilisé pour créer des fonctions dynamiques. Passer également le script sans exécuter le script.la source