为什么JavaScript函数总是返回值?

Why JavaScript functions always return a value?

我正在学习JavaScript编程课程,并且讲师说典型的JavaScript函数总是返回一个值。 即使我们不提供任何显式的返回值,引擎也会返回undefined

真的吗? 如果是这样,为什么?


的确如此,因为这就是JavaScript的设计方式。

但是我不认为这是您想要的答案,所以让我们考虑一下...
尝试让自己成为设计JavaScript的人Brendan Eich!

在静态语言中,通常不区分不返回任何值的函数(void函数)和返回某些值的函数。 Brendan选择设计一种动态语言,即不需要您定义函数返回类型的语言。因此,JavaScript不会检查您从函数返回的内容,从而给您充分的自由。

您可以使用一个返回数字的函数...

1
2
3
function computeSomething() {
  return 2;
}

...或字符串...

1
2
3
function computeSomething() {
  return 'hi';
}

...或者实际上是其中任何一个:

1
2
3
4
5
6
7
function computeSomething() {
  if (Math.random() > 0.5) {
    return 2;
  } else {
    return 'hello';
  }
}

有时您不需要计算任何东西,只需要做一些事情即可。
所以你什么都不退。

1
2
3
function doSomething() {
   console.log('doing something');
}

但是,我们可能想要退出函数的中间位置,并且由于return 已经完全做到了这一点,因此允许在没有值的情况下允许写入return是有意义的:

1
2
3
4
5
6
7
8
9
function doSomething(num) {
   if (num === 42) {
     return;
   }

   while (true) {
     doSomethingElse();
   }
}

这也与C / Java语法一致,后者是确保采用JavaScript的目标之一。

是的,有麻烦了:如果将普通的return放入应该计算某些内容的函数中,会发生什么?请注意,我们不能说这是非法的:我们先前的决定之一是使JavaScript成为一种动态语言,在这种情况下,我们不检查函数返回的内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function computeSomething(num) {
  if (num === 42) {
    return; // just return? o_O
  }

  if (Math.random() > 0.5) {
    return 2;
  } else {
    return 'hello';
  }
}

var x = computeSomething(2); // might be 2, might be 'hello'
var y = computeSomething(42); // ???

当然,布伦丹本可以决定在这种情况下引发错误,但他明智地决定不提出此类错误,因为这将导致难以发现的错误和容易破坏的代码。

因此,空的return的意思是"返回undefined"。

但是,函数返回早期还是结束有什么区别?从调用代码的角度来看,不应有任何内容。调用代码不应该确切知道何时返回该函数。它只对返回值(如果有)感兴趣。

因此,唯一的逻辑结论是,如果函数未通过显式的return 运算符指定undefined,则将undefined设为"默认"返回值。因此,return和函数执行到其最终语义是匹配的。

Python是JavaScript之前的另一种动态语言,它以相同的方式解决了此问题:如果函数未指定返回值,则返回None


这是ECMAScript规范

13.2.1 [[Call]] ...
6. Otherwise result.type must be normal. Return undefined.

本质上,任何JS函数都会被编译为好像其末尾具有隐式return undefined;

1
2
3
4
5
function foo() {
  ...

  return undefined; // implicit non-visible statement  
}

Even when we don't provide any explicit return value, the engines return"undefined". Is that true?

不是。据我了解,一个什么都不返回的函数……什么也不返回。也就是说,如果将变量分配给此类函数调用的结果,则表达式的计算结果为undefined

编辑

我站得住了。这是规范的相关部分:

13.2.1 [[通话]]

当使用this值和参数列表调用功能对象F的[[Call]]内部方法时,将执行以下步骤:

  • 令funcCtx为使用F的[[FormalParameters]]内部属性的值,传递的参数List args和this值(如10.4.3中所述)为功能代码建立新的执行上下文的结果。
  • 令result为评估FunctionBody的结果,FunctionBody是F的[[Code]]内部属性的值。如果F没有[[Code]]内部属性,或者它的值是一个空的FunctionBody,则结果为(正常,未定义,为空)。
  • 退出执行上下文funcCtx,还原先前的执行上下文。
  • 如果result.type被抛出,则抛出result.value。
  • 如果result.type为return,则返回result.value。
  • 否则result.type必须是正常的。返回未定义。

  • 在javascript中,函数是对象。因此,您总是可以像分配其他对象一样将函数分配给变量,并且解释器将强制确定一个值(可能未定义)。