javascript - tag - title html w3schools
¿De qué tipo es la palabra clave ''retorno''? (6)
Pero, ¿cuál es el tipo real de ''retorno'' en sí mismo?
No tiene un tipo, no es un valor.
Intento de tipo de
typeof return;
le dará un
Unexpected token return
.
Entonces, podemos pasar expresiones separadas por comas en la declaración de retorno. ¿Es esta una función?
No, aunque los paréntesis se pueden usar para llamar a una función, aquí se trata de un operador de agrupación que contiene un par de expresiones separadas por un operador de coma .
Una demostración más útil sería:
function add(a, b) {
return (
(a + b),
(a - b)
);
}
console.log(add(2, 2));
Que genera
0
porque el resultado de
a + b
se ignora (está en el LHS del operador de coma) y se devuelve a
a - b
.
Usamos declaraciones de
return
opcionalmente en funciones de JavaScript.
Es una palabra clave
Pero, ¿cuál es el tipo real de
return
sí?
En realidad me confundí al ver el ejemplo:
function add(a, b) {
return (
console.log(a + b),
console.log(arguments)
);
}
add(2, 2);
Salida:
4
[2, 2]
Entonces, podemos pasar expresiones separadas por comas en la declaración de
return
.
¿Es esta una función?
Y comenzando con esto, ¿podemos adivinar que cada palabra clave en JavaScript es en última instancia una función?
He escrito un pequeño blog como resumen de esta discusión. Es posible que desee consultarlo here .
El
return
aquí es un arenque rojo.
Quizás sea interesante la siguiente variación:
function add(a, b) {
return (
console.log(a + b),
console.log(arguments)
);
}
console.log(add(2, 2));
que sale como la última línea
undefined
ya que la función en realidad no devuelve nada.
(Devolvería el valor de retorno del segundo
console.log
, si tuviera uno).
Tal como está, el código es exactamente idéntico a
function add(a, b) {
console.log(a + b);
console.log(arguments);
}
console.log(add(2, 2));
Estoy un poco sorprendido de que nadie aquí haya hecho referencia directa a la especificación :
12.9 La sintaxis de declaración de devolución ReturnStatement: return; return [sin LineTerminator aquí] Expresión;
Semántica
Un programa ECMAScript se considera sintácticamente incorrecto si contiene una declaración de devolución que no está dentro de un FunctionBody. Una instrucción return hace que una función deje de ejecutarse y devuelva un valor al llamante. Si se omite Expression, el valor de retorno no está definido. De lo contrario, el valor de retorno es el valor de Expression.
Una declaración de devolución se evalúa de la siguiente manera:
Si la expresión no está presente, devuelve
(return, undefined, empty)
. Deje queexprRef
sea el resultado de evaluar Expression. Retorno(return, GetValue(exprRef), empty)
.
Entonces, debido a la especificación, su ejemplo dice:
return ( GetValue(exprRef) )
donde
exprRef = console.log(a + b), console.log(arguments)
Que de acuerdo con las especificaciones del operador de coma ...
Semántica
La expresión de producción: expresión, expresión de asignación se evalúa de la siguiente manera:
Let lref be the result of evaluating Expression. Call GetValue(lref). Let rref be the result of evaluating AssignmentExpression. Return GetValue(rref).
... significa que cada expresión se evaluará hasta el último elemento de la lista de comas, que se convierte en la expresión de asignación.
Entonces su código de
return (console.log(a + b) , console.log(arguments))
va a
1.) imprime el resultado de
a + b
2.) No queda nada para ejecutar, así que ejecute la siguiente expresión que
3.) imprime los
arguments
y porque
console.log()
no especifica una declaración de retorno
4.) Evalúa a indefinido
5.) Que luego se devuelve a la persona que llama.
Entonces, la respuesta correcta es,
return
no tiene un tipo, solo devuelve el resultado de alguna expresión.
Para la siguiente pregunta:
Entonces, podemos pasar expresiones separadas por comas en la declaración de retorno. ¿Es esta una función?
No. La coma en JavaScript es un operador, definido para permitirle combinar múltiples expresiones en una sola línea, y está definido por la especificación para devolver la expresión evaluada de lo que sea último en su lista.
¿Todavía no me crees?
<script>
alert(foo());
function foo(){
var foo = undefined + undefined;
console.log(foo);
return undefined, console.log(1), 4;
}
</script>
Juega con ese código
here
y juega con el último valor de la lista.
Siempre devolverá el último valor de la lista, en su caso, simplemente
undefined.
está
undefined.
Para tu pregunta final,
Y comenzando con esto, ¿podemos adivinar que cada palabra clave en JavaScript es en última instancia una función?
De nuevo no. Las funciones tienen una definición muy específica en el lenguaje. No lo volveré a imprimir aquí porque esta respuesta ya se está haciendo extremadamente larga.
Prueba de lo que sucede cuando devuelve valores entre paréntesis:
function foo() {
return (1, 2);
}
console.log(foo());
Da la respuesta
2
, por lo que parece que una lista de valores separados por comas se evalúa como el último elemento de la lista.
Realmente, los paréntesis son irrelevantes aquí, son operaciones de agrupación en lugar de significar una llamada a la función. Sin embargo, lo que posiblemente sea sorprendente es que la coma es legal aquí. Encontré una publicación de blog interesante sobre cómo se trata la coma aquí:
https://javascriptweblog.wordpress.com/2011/04/04/the-javascript-comma-operator/
Una forma interesante de entender la declaración de return es a través del operador void Eche un vistazo a este código
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" />
Dado que la declaración de
return
toma un argumento que es
[[expression]]
y lo devuelve al llamador en la pila, es decir
arguments.callee.caller
, ejecutará
void(expression)
y luego devolverá
undefined
que es la evaluación del operador vacío.
return
no es una función.
Es la
continuación
de la función en la que ocurre.
Piense en la
alert (2 * foo(bar));
declaración
alert (2 * foo(bar));
donde
foo
es el nombre de una función.
Cuando lo estás evaluando, ves que tienes que dejar a un lado el resto de la declaración por un momento para concentrarte en evaluar
foo(bar)
.
Podrías visualizar la parte que reservaste como algo como
alert (2 * _)
, con un espacio en blanco para completar. Cuando sabes cuál es el valor de
foo(bar)
, lo retomas nuevamente.
Lo que dejaste de lado fue la
continuación
de la llamada
foo(bar)
.
Llamar al
return
alimenta un valor a esa continuación.
Cuando evalúa una
función
dentro de
foo
, el resto de
foo
espera a que esa función se reduzca a un valor, y luego
foo
retoma nuevamente.
Todavía tiene un objetivo para evaluar
foo(bar)
, solo está en pausa.
Cuando evalúa el
return
dentro de
foo
, ninguna parte de
foo
espera un valor.
return
no se reduce a un valor en el lugar dentro de
foo
donde lo usó.
En cambio, hace que toda la
llamada
foo(bar)
reduzca a un valor, y el objetivo "evaluar
foo(bar)
" se considera completo y se desvanece.
La gente no suele contarte sobre las continuaciones cuando eres nuevo en la programación. Lo consideran un tema avanzado, solo porque hay algunas cosas muy avanzadas que las personas eventualmente hacen con las continuaciones. Pero la verdad es que los estás usando todo el tiempo, cada vez que llamas a una función.