函数表达式与函数声明:返回值

时间:2018-06-16 20:21:08

标签: javascript

在Udacity课程中,函数表达式和声明之间的区别解释如下:

  

函数声明定义一个函数,不需要   要分配给它的变量。它只是声明一个函数,并且   不会自己返回一个值...另一方面,一个函数   表达式确实返回一个值。

这令人困惑;据我所知,当函数表达式和函数声明都包含return语句时,都返回一个值。

如果我理解正确,返回值的差异在于函数表达式中,如果在函数的第一次调用中更改了值,则在后续调用中将保留更新的值 - 而如果函数如果没有存储在变量中,则在函数执行完毕后将返回返回值。我错过了什么,并且从课程中的陈述准确吗?

注意:我的问题与标记为重复的问题不同。在那个问题中,它询问使用其中一个的原因是什么,但问题中没有提到回复值,或者在答案中对其进行了解释。

5 个答案:

答案 0 :(得分:2)

定义不是讨论返回值的函数,而是谈论创建函数的一种方式如何返回一个值(这是函数表达式)而另一种只是声明一个函数(函数声明)。 / p>

为了帮助您澄清事情,您应该首先了解expression是什么:

  

表达式是解析为值的任何有效代码单元。

表达式的一个示例是x = 5,其计算结果为5。 另一个例子是3 + 2,它也评估为5

换句话说,我们可以说上面的两个表达式都返回5的值。

函数表达式只是一个返回(求值)函数的表达式:

// expression
const whatever = function expression() {}
//               ^^^^^^^^^^^^^^^^^^^^^^^^ this is the function expression in an assignment statement

函数声明不是表达式而是statement。 它不需要评估值。它立即宣布:

// declaration
function example() {}

如何创建函数(通过声明或表达式)不会影响函数返回的内容 - 在这两种情况下,该功能都是相同的。

答案 1 :(得分:2)

要了解这是什么,我们需要深入研究JavaScript语法:

在ECMAScript中,脚本由语句声明组成。 Statement 可以是(以及其他) ExpressionStatement 。请注意, ExpressionStatement 明确定义为:

  

ExpressionStatement [Yield,Await]:

     

[lookahead∉{{,functionasync [no LineTerminator 此处] functionclasslet [ }]

     

表达式 [+ In,?Yield,?Await];

这看起来非常麻烦,但它说的是 ExpressionStatement 不能以关键字function开头。所以,如果你只是写:

function a() {}

虽然在其他情况下如

,但永远不能将其解释为表达式
const a = function a() {}

这是一个表达。 (赋值操作的右侧必须始终是表达式。)

现在,只有表达式会评估一个值,而语句则不会。这是你引用的所有文字都难以理解的方式。

  

函数声明定义一个函数,不需要为其赋值:

真实但多余。声明不能出现在作业的右侧。

  

它只是声明一个函数,并且本身不返回值...

是的,陈述不评估(“返回”)一个值。

  

另一方面,函数表达式确实返回一个值。

当然,就像任何表达一样。

请参阅https://www.ecma-international.org/ecma-262/8.0/#prod-StatementList

答案 2 :(得分:1)

  
    

另一方面,函数表达式确实返回一个值。

  
     

这令人困惑

确实是的。它们的实际含义是函数表达式求值为(函数)值 - 与声明形成对比,声明不是表达式而是语句,并且不计算任何值。它与函数可能从调用返回的值无关。

答案 3 :(得分:0)

你说这个例子令人困惑是正确的。

如果你想到"返回价值"也许它会有所帮助在翻译的背景下?我的意思是,想象一下你是在自己解析Javascript(好像你是Chrome的v8)。

声明只会定义一个新的函数类型,并且在声明后可以使用它。

// declare a function named Declaration
function Declaration() { // stuff }

现在想象它是一个得到评估的表达式。

// named function expression
var foo = function FooFunc() { // do stuff }

// anonymous function expression
var foo = function () { // do stuff }

// a self-invoking anonymous function expression (example of a non-variable assingment
// The parentheses make it self-invoking and not a declaration.
(function foo() { console.log('foo'); })() // outputs 'foo' when parsed
+function foo() { console.log('foo'); }(); // same as above
!function foo() { console.log('foo'); }(); // same as above
-function foo() { console.log('foo'); }(); // same as above
~function foo() { console.log('foo'); }(); // same as above

首先,看看是否要进行任务(或自我执行)。通过检查constvar(来执行此操作。

假设表达式是变量赋值var foo = function fooFunc() {}

在这种情况下,解释器知道当你定义fooFunc时,你也希望定义的结果 - fooFunc函数 - 是{{foo的值。 1}}所以有一个"返回值" - fooFunc函数对象 - 需要分配。

答案 4 :(得分:0)

起初这可能很难学,但让我们尝试不同的方法。

他们不是在谈论函数调用的返回值,而是关于表达式的值(在其他答案中也有解释)。

您可以使用Chrome开发者工具中的控制台查看每个expreassion评估的内容,例如:如果您在控制台中输入10,则此表达式将返回10

> 10
< 10

等等......

> 10 + 5
< 15

> 'Hello world!'
< "Hello world!"

为变量赋值(不是varconstlet)会返回变量new value,因此您可以在控制台中看到:

> n = 10
< 10

> var foo = (n = 10) // also `var foo = n = 10` or `foo = n = 10`
< undefined

> foo
< 10

> n
< 10

> (obj = {}).foo = 'bar'
< "bar"

> obj
< {foo: "bar"}

当我们讨论函数时,它的声明不返回任何值,但是函数表达式返回对创建的函数的引用,这就是为什么你可以将它赋给变量。

> function foo() { }
< undefined

> (function() { })
< ƒ () { }

这就是为什么你可以做以下事情:

> (function() { return 'it works!' })()
< "it works!"

> myFunc = function() { return 'also works!' }
< ƒ () { return 'also works!' }

> myFunc()
< "also works!"

希望这能帮到你。 :)