web-dev-qa-db-fra.com

De quel type est le mot-clé «retour»?

Nous utilisons les instructions return facultativement dans les fonctions JavaScript. C'est un mot-clé. Mais quel est le type réel de return lui-même. En fait, je me suis perdu, en voyant l'exemple:

function add(a, b) {
  return (
    console.log(a + b),
    console.log(arguments)
  );
}

add(2, 2);

Sortie:

4
[2, 2]

Ainsi, nous pouvons passer des expressions séparées par des virgules dans l'instruction return. Est-ce une fonction?

Et à partir de là, pouvons-nous deviner que tous les mots clés de JavaScript sont finalement une fonction?

J'ai écrit un petit blog comme un résumé de cette discussion. Vous voudrez peut-être le vérifier ici .

95
Arnab Das

Mais quel est le type réel de "retour" lui-même.

Il n'a pas de type, ce n'est pas une valeur.

Tentative typeof return; te donnera Unexpected token return.

Ainsi, nous pouvons passer des expressions séparées par des virgules dans l'instruction de retour. Est-ce une fonction?

Non, alors que les parenthèses peuvent être utilisées pour appeler une fonction, elles sont ici un opérateur de regroupement contenant quelques expressions séparées par un opérateur virgule .

Une démonstration plus utile serait:

function add(a, b) {
  return (
    (a + b),
    (a - b)
  );
}

console.log(add(2, 2));

Quelles sorties 0 car le résultat de a + b est ignoré (il se trouve sur le LHS de l'opérateur virgule) et a - b est retourné.

129
Quentin

Je suis un peu choqué que personne ici n'ait directement référencé la spécification :

12.9 La syntaxe de l'instruction return ReturnStatement: return; return [pas de LineTerminator ici] Expression;

Sémantique

Un programme ECMAScript est considéré comme syntaxiquement incorrect s'il contient une instruction de retour qui n'est pas dans un FunctionBody. Une instruction return oblige une fonction à cesser son exécution et à renvoyer une valeur à l'appelant. Si Expression est omis, la valeur de retour n'est pas définie. Sinon, la valeur de retour est la valeur de Expression.

Un ReturnStatement est évalué comme suit:

Si l'expression n'est pas présente, retournez (return, undefined, empty). Soit exprRef le résultat de l'évaluation de l'expression. Retournez (return, GetValue(exprRef), empty).

Donc, à cause de la spécification, votre exemple se lit comme suit:

return ( GetValue(exprRef) )

exprRef = console.log(a + b), console.log(arguments)

Selon le spécification sur l'opérateur virgule ...

Sémantique

L'expression de production: Expression, AssignmentExpression est évaluée comme suit:

Let lref be the result of evaluating Expression.
Call GetValue(lref).
Let rref be the result of evaluating AssignmentExpression.
Return GetValue(rref).

... signifie que chaque expression sera évaluée jusqu'au dernier élément de la liste des virgules, qui devient l'expression d'affectation. Donc, votre code return (console.log(a + b) , console.log(arguments)) va

1.) imprimez le résultat de a + b

2.) Il ne reste rien à exécuter, donc exécutez l'expression suivante qui

3.) affiche le arguments, et parce que console.log() ne spécifie pas de déclaration de retour

4.) Évalue à indéfini

5.) Qui est ensuite retourné à l'appelant.

La bonne réponse est donc que return n'a pas de type, il ne renvoie que le résultat d'une expression.

Pour la question suivante:

Ainsi, nous pouvons passer des expressions séparées par des virgules dans l'instruction de retour. Est-ce une fonction?

Non. La virgule en JavaScript est un opérateur, défini pour vous permettre de combiner plusieurs expressions en une seule ligne, et est défini par la spécification pour renvoyer l'expression évaluée de ce qui est le dernier de votre liste.

Tu ne me crois toujours pas?

<script>
alert(foo());
function foo(){
    var foo = undefined + undefined;
    console.log(foo);
    return undefined, console.log(1), 4;
}
</script>

Jouez avec ce code ici et jouez avec la dernière valeur de la liste. Il renverra toujours la dernière valeur de la liste, dans votre cas, il se trouve juste être undefined.

Pour votre dernière question,

Et à partir de là, pouvons-nous deviner que tous les mots clés de JavaScript sont finalement une fonction?

Encore une fois, non. Les fonctions ont une définition très spécifique dans la langue. Je ne le réimprimerai pas ici car cette réponse devient déjà extrêmement longue.

32
avgvstvs

Test de ce qui se passe lorsque vous renvoyez des valeurs entre parenthèses:

function foo() {
    return (1, 2);
}

console.log(foo());

Donne la réponse 2, il apparaît donc qu'une liste de valeurs séparées par des virgules correspond au dernier élément de la liste.

Vraiment, les parenthèses ne sont pas pertinentes ici, elles regroupent des opérations au lieu de signifier un appel de fonction. Ce qui est peut-être surprenant, cependant, c'est que la virgule est légale ici. J'ai trouvé un article de blog intéressant sur la façon dont la virgule est traitée ici:

https://javascriptweblog.wordpress.com/2011/04/04/the-javascript-comma-operator/

15
SpoonMeiser

return n'est pas une fonction. C'est le suite de la fonction dans laquelle il se produit.

Pensez à l'instruction alert (2 * foo(bar));foo est le nom d'une fonction. Lorsque vous l'évaluez, vous voyez que vous devez mettre de côté le reste de l'instruction pendant un moment pour vous concentrer sur l'évaluation de foo(bar). Vous pouvez visualiser la pièce que vous mettez de côté comme quelque chose comme alert (2 * _), avec un blanc à remplir. Lorsque vous savez quelle est la valeur de foo(bar), vous la récupérez.

La chose que vous avez mise de côté était le suite de l'appel foo(bar).

L'appel de return alimente une valeur à cette continuation.

Lorsque vous évaluez une fonction à l'intérieur de foo, le reste de foo attend que cette fonction soit réduite à une valeur, puis foo reprend . Vous avez toujours un objectif pour évaluer foo(bar), c'est juste une pause.

Lorsque vous évaluez return dans foo, aucune partie de foo n'attend une valeur. return ne se réduit pas à une valeur à l'intérieur de foo où vous l'avez utilisé. Au lieu de cela, il entraîne la réduction de la valeur de callfoo(bar) dans son intégralité, et l'objectif "evaluer foo(bar)" est considéré comme terminé et est supprimé.

Les gens ne vous parlent généralement pas des suites lorsque vous débutez en programmation. Ils le considèrent comme un sujet avancé, juste parce qu'il y a sont des choses très avancées que les gens finissent par faire avec des continuations. Mais la vérité est que vous les utilisez depuis le début, chaque fois que vous appelez une fonction.

9

le return voici un hareng rouge. Peut-être intéressant est la variation suivante:

function add(a, b) {
  return (
    console.log(a + b),
    console.log(arguments)
  );
}

console.log(add(2, 2));

qui sort comme dernière ligne

undefined

car la fonction ne retourne rien. (Il retournerait la valeur de retour du second console.log, s'il en avait un).

En l'état, le code est exactement identique à

function add(a, b) {
    console.log(a + b);
    console.log(arguments);
}

console.log(add(2, 2));
6
ths

Une façon intéressante de comprendre l'instruction return est d'utiliser l'opérateur void Jetez un œil à ce code

var console = {
    log: function(s) {
      document.getElementById("console").innerHTML += s + "<br/>"
    }
}

function funReturnUndefined(x,y) {
   return ( void(x+y) );
}

function funReturnResult(x,y) {
   return ( (x+y) );
}

console.log( funReturnUndefined(2,3) );
console.log( funReturnResult(2,3) );
<div id="console" />

Étant donné que l'instruction return prend un argument qui est [[expression]] Et le renvoie à l'appelant sur la pile, c'est-à-dire arguments.callee.caller, Il exécutera alors void(expression) puis retournera undefined c'est l'évaluation de l'opérateur void.

1
loretoparisi