什么types是“返回”关键字?
我们可以在JavaScript函数中使用return语句。 这是一个关键字。 但是什么是实际的return
本身。 其实我感到困惑,看到这样的例子:
function add(a, b) { return ( console.log(a + b), console.log(arguments) ); } add(2, 2);
输出:
4 [2, 2]
所以,我们可以将逗号分隔的expression式传递给return
语句。 这是一个function?
从这个开始,我们可以大胆猜测,JavaScript中的每个关键字最终都是一个函数吗?
我已经写了一个小博客作为这个讨论的要点。 你可能想在这里检查。
但是什么是“回报”本身的实际types。
它没有一个types,它不是一个值。
试图typeof return;
会给你Unexpected token return
。
所以,我们可以将逗号分隔的expression式传递给return语句。 这是一个function?
不,括号可以用来调用一个函数,在这里它们是一个分组操作符,包含一个由逗号分隔符分隔的几个expression式。
更有用的演示将是:
function add(a, b) { return ( (a + b), (a - b) ); } console.log(add(2, 2));
哪个输出0
因为a + b
的结果被忽略(它在逗号运算符的LHS上)并返回a - b
。
我有点震惊,没有人直接引用规范 :
12.9返回语句语法ReturnStatement:return; 返回[这里没有LineTerminator]expression式;
语义
如果ECMAScript程序包含不在FunctionBody内的返回语句,则ECMAScript程序在语法上被认为是不正确的。 返回语句会导致函数停止执行并向调用者返回一个值。 如果Expression被省略,则返回值是未定义的。 否则,返回值就是Expression的值。
ReturnStatement评估如下:
如果Expression不存在,则返回
(return, undefined, empty)
。 让exprRef
是评估expression式的结果。 返回(return, GetValue(exprRef), empty)
。
所以,由于规范,你的例子是:
return ( GetValue(exprRef) )
其中exprRef = console.log(a + b), console.log(arguments)
根据逗号运算符的规格 …
语义
生产Expression:Expression,AssignmentExpression的计算方法如下:
Let lref be the result of evaluating Expression. Call GetValue(lref). Let rref be the result of evaluating AssignmentExpression. Return GetValue(rref).
…意味着每个expression式都会被评估,直到逗号列表中的最后一项成为分配expression式。 所以你的代码return (console.log(a + b) , console.log(arguments))
1.)打印a + b
的结果
2)什么也没有执行,所以执行下一个expression式
3.)打印arguments
,因为console.log()
没有指定返回语句
4.)评估为未定义
5.)然后返回给调用者。
所以正确答案是, return
没有types,它只返回一些expression式的结果。
对于下一个问题:
所以,我们可以将逗号分隔的expression式传递给return语句。 这是一个function?
不可以。JavaScript中的逗号是一个运算符,它定义为允许您将多个expression式组合到一行中,并由规范定义,以返回列表中最后一个元素的评估expression式。
你还不相信我?
<script> alert(foo()); function foo(){ var foo = undefined + undefined; console.log(foo); return undefined, console.log(1), 4; } </script>
在这里玩这个代码,搞乱列表中的最后一个值。 它总是会返回列表中的最后一个值,在你的情况下,它恰好是undefined.
对于你最后的问题,
从这个开始,我们可以大胆猜测,JavaScript中的每个关键字最终都是一个函数吗?
再次,不。 函数在语言中有一个非常具体的定义 。 我不会在这里重印,因为这个答案已经非常长了。
testing返回括号值时会发生什么情况:
function foo() { return (1, 2); } console.log(foo());
给出答案2
,所以看起来逗号分隔值列表的计算结果是列表中的最后一个元素。
真的,括号在这里是不相关的,他们是分组操作,而不是表示函数调用。 但令人惊讶的是,逗号在这里是合法的。 我在这里find了一个有趣的博客文章:
https://javascriptweblog.wordpress.com/2011/04/04/the-javascript-comma-operator/
return
不是一个函数。 这是它发生的function的延续 。
考虑一下语句alert (2 * foo(bar));
其中foo
是函数的名称。 当你评估它的时候,你会发现你必须暂时搁置声明的其余部分,集中精力评估foo(bar)
。 你可以将你所预留的部分看作是alert (2 * _)
,并填上一个空格。当你知道foo(bar)
的值是什么时,你再次拾取它。
你留下的东西是foo(bar)
。
调用return
给这个延续提供一个值。
当你在foo
里面计算一个函数时 , foo
的其余部分等待这个函数减less到一个值,然后foo
再次提取。 你仍然有一个目标来评估foo(bar)
,它只是暂停。
当你评价foo
内部的return
, foo
任何部分都不会等待一个值。 return
值不会减less到你使用它的foo
内部的某个值。 相反,它会导致整个调用 foo(bar)
减less到一个值,并且“评估foo(bar)
”的目标被视为完整并被吹走。
当你不熟悉编程时,人们通常不会告诉你什么是延续。 他们认为这是一个先进的话题,只是因为人们最终做了一些非常先进的事情。 但事实是,每当你调用一个函数,你就一直在使用它们。
这里的return
是红鲱鱼。 也许有趣的是下面的变化:
function add(a, b) { return ( console.log(a + b), console.log(arguments) ); } console.log(add(2, 2));
作为最后一行输出
undefined
因为该函数实际上不会返回任何东西。 (它会返回第二个console.log
的返回值,如果有的话)。
就像这样,代码完全一样
function add(a, b) { console.log(a + b); console.log(arguments); } console.log(add(2, 2));
理解return语句的一个有趣的方法是通过void操作符来看看这段代码
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" />