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

Luí*_*ção 52 javascript

我正在学习JavaScript编程课程,教师说一个典型的JavaScript函数总是返回一个值.即使我们没有提供任何明确的返回值,引擎也会返回undefined.

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

Dan*_*mov 91

这是真的 - 因为这就是JavaScript的设计方式.

但我认为这不是你想要的答案,所以让我们考虑一下......
试着让自己置身于设计JavaScript的人Brendan Eich的脚下!

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

你可以有一个返回数字的函数......

function computeSomething() {
  return 2;
}
Run Code Online (Sandbox Code Playgroud)

......或一串......

function computeSomething() {
  return 'hi';
}
Run Code Online (Sandbox Code Playgroud)

......或者,事实上,其中任何一个:

function computeSomething() {
  if (Math.random() > 0.5) {
    return 2;
  } else {
    return 'hello';
  }
}
Run Code Online (Sandbox Code Playgroud)

有时你不需要计算任何东西 - 你只需要做一些事情.
所以你不回报任何东西.

function doSomething() {
   console.log('doing something');
}
Run Code Online (Sandbox Code Playgroud)

但是,我们可能希望在它的中间退出一个函数,并且因为return <value>已经完全正确,所以允许在return没有值的情况下写入来支持这个用例是有意义的:

function doSomething(num) {
   if (num === 42) {
     return;
   }

   while (true) {
     doSomethingElse();
   }
}
Run Code Online (Sandbox Code Playgroud)

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

是的,有一个问题:如果我们将一个平台return放入一个应该计算某事的函数中会发生什么?请注意,我们不能取缔这一点:我们之前的一个决定是将JavaScript作为动态语言,我们不会检查函数返回的内容.

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); // ???
Run Code Online (Sandbox Code Playgroud)

当然Brendan本可以决定在这种情况下提出一个错误,但他明智地决定不这样做,因为它会导致难以发现的错误和太容易破解的代码.

所以空洞return的意思是"回归undefined".

但是早期或最后返回的函数有什么区别?从调用代码的角度来看,应该没有任何东西.调用代码不应该知道函数何时返回; 它只对返回值感兴趣(如果有的话).

因此,唯一合乎逻辑的结论是,undefined如果函数没有通过显式return <value>运算符指定一个,则使"默认"返回值.因此,return函数执行到它的结束语义匹配.

Python是另一种在JavaScript之前出现的动态语言,它以同样的方式解决了这个问题:None如果函数没有指定返回值,则返回.

  • 很棒的答案!您可以分析此设计决策的含义和原因,而不仅仅是反思部分规范. (10认同)
  • 人们总是抱怨JavaScript的不良部分 - 并且有很多 - 但是男孩,只有**这么多**部分的语言非常漂亮. (9认同)
  • "默认/未定义"值的概念通常用作语言中的概念.一旦你介绍了一个,你可以做一些简单的事情,比如检查一个参数是否被传递(就像在JS中完成的那样),并且不从void函数返回undefined会很奇怪. (2认同)

c-s*_*ile 13

这是ECMAScript规范

13.2.1 [[Call]] ... 6.否则result.type必须正常.返回undefined.

基本上任何JS函数都被编译为好像它最后是隐式return undefined;的:

function foo() {
  ...

  return undefined; // implicit non-visible statement  
}
Run Code Online (Sandbox Code Playgroud)


Ada*_*kis 7

即使我们没有提供任何明确的返回值,引擎也会返回"undefined".真的吗?

并不是的.据我所知,一个什么都不返回的函数......什么都不返回.也就是说,如果将变量分配给这样的函数调用的结果,那么表达式将计算为undefined.

编辑

我纠正了.这是规范的相关部分:


13.2.1 [[Call]]

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

  1. 假设funcCtx是使用F的[[FormalParameters]]内部属性的值,传递的参数List args以及10.4.3中描述的该值为函数代码建立新的执行上下文的结果.
  2. 假设结果是评估FunctionBody的结果,即Function的[[Code]]内部属性的值.如果F没有[[Code]]内部属性或其值为空FunctionBody,则结果为(normal,undefined,empty).
  3. 退出执行上下文funcCtx,恢复先前的执行上下文.
  4. 如果result.type是throw,则抛出result.value.
  5. 如果result.type是return,则返回result.value.
  6. 否则result.type必须正常.返回undefined.

  • 严格来说,这是[不正确](http://stackoverflow.com/a/20915520/458193). (4认同)
  • 谢谢@Dan - 我担心一些赞成票和青铜徽章是关于我可以提供的所有报酬:) (2认同)