在Udacity课程中,函数表达式和声明之间的区别解释如下:
函数声明定义一个函数,不需要 要分配给它的变量。它只是声明一个函数,并且 不会自己返回一个值...另一方面,一个函数 表达式确实返回一个值。
这令人困惑;据我所知,当函数表达式和函数声明都包含return语句时,都返回一个值。
如果我理解正确,返回值的差异在于函数表达式中,如果在函数的第一次调用中更改了值,则在后续调用中将保留更新的值 - 而如果函数如果没有存储在变量中,则在函数执行完毕后将返回返回值。我错过了什么,并且从课程中的陈述准确吗?
注意:我的问题与标记为重复的问题不同。在那个问题中,它询问使用其中一个的原因是什么,但问题中没有提到回复值,或者在答案中对其进行了解释。
答案 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∉{{,
function
,async
[no LineTerminator 此处]function
,class
,let
[ }]表达式 [+ 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
首先,看看是否要进行任务(或自我执行)。通过检查const
或var
或(
来执行此操作。
假设表达式是变量赋值var foo = function fooFunc() {}
。
在这种情况下,解释器知道当你定义fooFunc
时,你也希望定义的结果 - fooFunc
函数 - 是{{foo
的值。 1}}所以有一个"返回值" - fooFunc
函数对象 - 需要分配。
答案 4 :(得分:0)
起初这可能很难学,但让我们尝试不同的方法。
他们不是在谈论函数调用的返回值,而是关于表达式的值(在其他答案中也有解释)。
您可以使用Chrome开发者工具中的控制台查看每个expreassion评估的内容,例如:如果您在控制台中输入10
,则此表达式将返回10
> 10
< 10
等等......
> 10 + 5
< 15
> 'Hello world!'
< "Hello world!"
为变量赋值(不是var
,const
或let
)会返回变量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!"
希望这能帮到你。 :)