6312
|
Richard Garside · 技术社区 · 16 年前 |
![]() |
1
4686
区别在于
例如,函数表达式:
以及函数声明:
这也意味着您不能使用函数声明有条件地定义函数:
上面实际上定义了
|
![]() |
2
1851
首先我想纠正格雷格:
其次,可以将这两种风格结合起来:
如果要在所有浏览器上对函数进行别名,请使用以下声明:
在这种情况下,两者都是
使用组合样式的一个令人信服的原因是函数对象的“name”属性( Internet Explorer不支持 )基本上当你定义一个函数
它的名称是自动分配的。但是当你把它定义成
它的名称是空的——我们创建了一个匿名函数,并将它赋给了某个变量。 使用组合样式的另一个好理由是使用短的内部名称引用自身,同时为外部用户提供一个长的、无冲突的名称:
在上面的示例中,我们可以对外部名称执行相同的操作,但这样做会非常笨拙(而且速度也很慢)。
(引用自身的另一种方法是使用
在深层次上,javascript对这两个语句的处理方式不同。这是一个函数声明:
同时,它通过
这是一个函数表达式:
函数声明与函数表达式是Greg证明存在差异的真正原因。 有趣的事实:
我个人更喜欢“函数表达式”声明,因为这样我可以控制可见性。当我把函数定义为
我知道我在本地定义了函数。当我把函数定义为
我知道我在全球范围内定义它,前提是我没有定义
取决于上下文,可能会让您猜测它的实际定义,尤其是在
|
![]() |
3
577
下面是创建函数的标准表单的概要: (最初是为另一个问题写的,但在进入规范问题后进行了修改。) 条款:
快速清单:
函数声明第一种形式是 函数声明 ,如下所示:
函数声明是
宣言
它不是语句或表达式。因此,你不能用
当执行进入其出现的上下文时,将处理函数声明,
之前
执行任何分步代码。它创建的函数有一个正确的名称(
因为它是在同一上下文中的任何逐步代码之前处理的,所以您可以这样做:
在ES2015之前,如果您将一个函数声明放在一个类似于
因为它们被处理过 之前 一步一步地运行代码,当它们处于控制结构中时,很难知道该怎么做。 尽管这样做不是 明确规定 在ES2015年之前, 允许延伸 支持块中的函数声明。不幸的是(不可避免的),不同的引擎做了不同的事情。 截至ES2015年,规范规定了该做什么。实际上,它提供了三个单独的任务:
松散模式的规则很复杂,但是 严格的 模式,块中的函数声明很容易:它们是块的本地声明(它们有 块范围 在ES2015年也是新的),它们被吊到了大楼的顶部。所以:
“匿名”
|
![]() |
4
138
谈到全球环境,两者都是
这两种方法之间的细微差别在于
Variable Instantiation
进程运行(在实际代码执行之前)用
转让
由创建的全局属性
两个示例之间的另一个明显区别是,第一个函数没有名称,但第二个函数有名称,这在调试(即检查调用堆栈)时非常有用。
关于您编辑的第一个示例(
有任务,没有
另外,未声明的工作分配
必须阅读:
注释
:此答案已合并自
another question
其中,OP的主要疑问和误解是,标识符声明为
|
![]() |
5
116
您在那里发布的两个代码片段在几乎所有目的上都将以相同的方式运行。
然而,行为上的区别在于第一种变体(
第二种变体(
这是因为对于第一个变量,函数被分配给变量
更多技术信息 javascript有三种定义函数的方法。
|
![]() |
6
97
更好的解释 Greg's answer
为什么没有错误?我们一直被教导,表达是自上而下执行的。?) 因为:
这意味着这样的代码:
注意声明的分配部分没有被提升。只有名字被提升。 但在有函数声明的情况下,整个函数体也将被提升 :
|
![]() |
7
88
其他评论者已经讨论了上述两种变体的语义差异。我想指出一个风格上的区别:只有“赋值”变体可以设置另一个对象的属性。 我经常用这样的模式构建JavaScript模块:
使用这种模式,公共函数将全部使用赋值,而私有函数使用声明。 (还请注意,赋值应该在语句后使用分号,而声明禁止使用分号。) |
![]() |
8
74
当您需要避免重写函数以前的定义时,可以说明何时首选第一个方法而不是第二个方法。 用
,此定义
同时
定义是否正确
|
![]() |
9
60
一个重要的原因是添加一个而且只有一个变量作为名称空间的“根”…
或
名称间距有很多种技术。随着大量可用的javascript模块的出现,它变得更加重要。 |
![]() |
10
52
Hoisting 是javascript解释器将所有变量和函数声明移动到当前作用域顶部的操作。 但是,只悬挂实际申报。把任务留在原地。
JavaScript被称为松散类型语言。这意味着javascript变量可以保存 Data-Type . javascript会根据运行时提供的值/文字自动更改变量类型。
功能
函数声明
函数表达式
分配给变量的函数示例:
javascript解释为
您可以检查函数声明,表达式测试不同浏览器的使用
ES5 Constructor Function Classes :使用function.prototype.bind创建的函数对象 javascript将函数视为第一类对象,因此作为一个对象,您可以为函数分配属性。
引入ES6 箭头函数 :箭头函数表达式的语法较短,最适合非方法函数,不能用作构造函数。
|
![]() |
11
36
我在补充我自己的答案,只是因为其他人都彻底地覆盖了起重部分。 很长一段时间以来,我一直想知道哪条路更好,多亏了 http://jsperf.com 现在我知道:
函数声明 更快,这就是Web开发中真正重要的东西,对吗?;) |
![]() |
12
32
一旦建立绑定,分配给变量的函数声明和函数表达式的行为就相同。 但是在 怎样 和 什么时候? 函数对象实际上与其变量相关联。这种差异是由于 变量提升 在JavaScript中。 基本上,所有函数声明和变量声明都被提升到 功能 声明发生的地方(这就是为什么我们说javascript 功能范围 )
提升的顺序也很重要:函数声明优先于同名的变量声明,最后一个函数声明优先于同名的前一个函数声明。 一些例子…
变量
函数声明优先于变量声明,最后一个函数声明“stick”。
在这个例子中
这里首先提升函数声明,声明并初始化变量
|
![]() |
13
30
第一个示例是函数声明:
第二个例子是函数表达式:
主要区别在于它们的提升(提升和申报)方式。在第一个示例中,将提升整个函数声明。在第二个例子中,只有var'abc'被提升,它的值(函数)将不被定义,并且函数本身保持在它被声明的位置。 简单来说:
为了进一步研究这个话题,我强烈推荐你 link |
![]() |
14
28
在代码维护成本方面,命名函数更可取:
我怀疑后面还有更多的命名函数的优点。而被列为命名函数的优点的是匿名函数的缺点。 从历史上看,匿名函数是由于javascript无法作为一种语言列出具有命名函数的成员:
|
![]() |
15
24
我在代码中使用变量方法有一个非常具体的原因,上面抽象地介绍了它的理论,但是一个例子可能会帮助像我这样的人,因为JavaScript专业知识有限。 我有一些代码需要使用160个独立设计的品牌来运行。大多数代码都在共享文件中,但是特定于品牌的东西在一个单独的文件中,每个品牌对应一个文件。 有些品牌需要特定的功能,有些则不需要。有时我必须添加新的功能来执行新的品牌特定的事情。我很乐意更改共享代码,但我不想更改所有160组品牌文件。 通过使用变量语法,我可以在共享代码中声明变量(本质上是一个函数指针),并分配一个普通的存根函数,或者设置为空。 然后,需要特定实现函数的一个或两个Brandings可以定义函数的版本,并根据需要将其分配给变量,其余的什么也不做。我可以在共享代码中执行空函数之前测试它。 从上面的人们的评论中,我认为重新定义一个静态函数也是可能的,但是我认为变量解是好的和清晰的。 |
![]() |
16
22
在计算机科学术语中,我们讨论匿名函数和命名函数。我认为最重要的区别是一个匿名函数没有绑定到一个名称,因此这个名称是匿名函数。在JavaScript中,它是在运行时动态声明的第一类对象。 有关匿名函数和lambda微积分的更多信息,维基百科是一个很好的开始。( http://en.wikipedia.org/wiki/Anonymous_function ) |
![]() |
17
22
Greg's Answer 已经够好了,但我还是想增加一些我刚刚学过的东西 Douglas Crockford's 视频。 函数表达式:
函数语句:
函数语句只是
所以
扩展到
进一步扩展到:
它们都被提升到代码的顶端。
|
![]() |
18
18
@EugeneLazutkin
举个例子
names an assigned function to be able to use
教程中的示例:递归调用
Tests fail when the original ninja object is removed. (第13页)
If you name the function that will be called recursively, the tests will pass. (第14页)
|
![]() |
19
16
其他答案中没有提到的另一个区别是,如果使用匿名函数
并将其用作构造函数
然后
用
可以使用
|
![]() |
20
14
如果要使用这些函数创建对象,您将得到:
|
![]() |
21
14
第一个(函数dosomething(x))应该是对象符号的一部分。
第二个(
你可能想知道 函数声明 和 函数表达式 是。 函数声明定义一个命名的函数变量,而不需要变量赋值。函数声明作为独立结构出现,不能嵌套在非函数块中。
在上述条件下,函数名在其作用域和其父级作用域内可见(否则将无法访问)。 在函数表达式中 函数表达式将函数定义为较大表达式语法(通常是变量赋值)的一部分。通过函数表达式定义的函数可以命名或匿名。函数表达式不应以__函数__开头。
|
![]() |
22
14
我将列出以下差异:
|
![]() |
23
12
根据“命名函数出现在堆栈跟踪中”的参数,现代的JavaScript引擎实际上非常能够表示匿名函数。 在这篇文章中,V8、蜘蛛猴、脉轮和硝基总是用它们的名字来表示命名函数。如果一个匿名函数有标识符的话,它们几乎总是通过它的标识符来引用它。 spidermonkey可以找出从另一个函数返回的匿名函数的名称。其余的不能。 如果您真的非常希望迭代器和成功回调出现在跟踪中,那么您也可以将它们命名为……
但在很大程度上,这不值得去强调。 挽具 Fiddle )
V8
蜘蛛猴
脉轮
硝基
|
![]() |
24
11
下面列出了两种不同的函数声明之间的四个值得注意的比较。
以下工作是因为
以下内容不起作用(因为
以下内容不起作用,因为
函数的名称
否则,如果函数声明为
如果没有为函数设置变量,则函数名为空字符串(
最后,当分配给函数的变量最初设置名称时,设置给函数的连续变量不会更改名称。
在谷歌的V8和火狐的蜘蛛猴中,可能存在几微秒的JIST编译差异,但最终结果是完全相同的。为了证明这一点,让我们通过比较两个空白代码片段的速度来检查微基准处JSPerf的效率。这个 JSPerf tests are found here . 而且, jsben.ch testsare found here . 正如你所看到的,当应该没有的时候有一个明显的区别。如果您真的像我一样是一个性能怪人,那么在尝试减少范围内的变量和函数的数量,特别是消除多态性(例如使用同一个变量存储两个不同的类型)的同时,它可能更有价值。
当你使用
但是,当我们使用const语句时,变量引用变得不可变。这意味着我们不能给变量赋值。但是,请注意,这不会使变量的内容不可变:如果这样做
有趣的是,如果我们将变量声明为
最近的街区是什么
“最近的块”是最近的“函数”(包括异步函数、生成器函数和异步生成器函数)。然而,有趣的是,
|
![]() |
25
10
在javascript中,有两种创建函数的方法:
参考文献: JavaScript function declaration syntax: var fn = function() {} vs function fn() {} |
![]() |
26
8
两者都是定义函数的不同方法。不同之处在于浏览器如何解释它们并将它们加载到执行上下文中。 第一种情况是函数表达式,它只在解释器到达该行代码时加载。因此,如果您像下面这样做,您将得到一个错误, 函数one不是函数 .
原因是在第一行中没有给functionone赋值,因此它是未定义的。我们试图把它称为函数,因此我们得到了一个错误。 在第二行中,我们将一个匿名函数的引用赋给functionone。 第二种情况是在执行任何代码之前加载的函数声明。因此,如果您这样做,那么在代码执行之前加载声明时不会得到任何错误。
|
![]() |
27
8
关于性能:
新版本
现在表达式和声明之间几乎没有区别。
|
![]() |
28
7
它们非常相似,但有一些小的区别,第一个是分配给匿名函数(函数声明)的变量,第二个是在javascript(匿名函数声明)中创建函数的正常方式,两者都有用法、缺点和优点:
1。函数表达式
给一个函数分配一个变量,意味着没有提升,正如我们所知道的,javascript中的函数可以提升,意味着它们可以在声明之前被调用,而变量需要在获得对它们的访问之前被声明,所以在这种情况下,我们不能在声明之前访问函数,也可能是您编写函数的一种方式。对于返回另一个函数的函数,这种声明可能是有意义的,同样在上面的ecma6&中,您可以将其分配给一个可用于调用匿名函数的arrow函数,而且这种声明方法是在javascript中创建构造函数函数的更好方法。
2。函数声明
这是在javascript中调用函数的正常方法,在您将其声明为在javascript中所有函数都被提升之前,可以调用该函数,但是如果您有“使用严格”,这将不会像预期的那样提升,这是调用所有行中不是大的、也不是构造函数函数的正常函数的好方法。 此外,如果您需要更多有关Javascript中提升工作方式的信息,请访问以下链接: |
![]() |
29
5
这只是两种可能的函数声明方法,第二种方法是在声明之前使用函数。 |
![]() |
30
4
|
![]() |
Hard_Course · 用另一列中的值替换行的最后一个非NA条目 5 月前 |
![]() |
KGB91 · 初始化一个用C存储函数的字典# 6 月前 |
![]() |
RobertF · 如何将函数应用于矩阵的每个元素? 7 月前 |
![]() |
user2986042 · C编译错误“调用的对象不是函数或函数指针” 11 月前 |