查看 JavaScript 代码,我看到了这两种类型的函数:
function EjemploUno(){
//código
}
var EjemploDos = function(){
//código
}
那么,一个和另一个有什么区别?什么时候应该使用一个或另一个?
查看 JavaScript 代码,我看到了这两种类型的函数:
function EjemploUno(){
//código
}
var EjemploDos = function(){
//código
}
那么,一个和另一个有什么区别?什么时候应该使用一个或另一个?
不同之处在于,在第一种情况下,它是一个命名函数
EjemploUno
,而在第二种情况下,它是一个分配给名称变量的匿名函数EjemploDos
我们可以使用该属性轻松验证这一点
.name
,如此代码片段所示在第一种情况下,我们得到了预期的结果
EjemploUno
,而在第二种情况下,我们得到了一个空字符串,因为函数是匿名的由于函数的名称与分配给函数的变量的名称不同,我们还可以有以下内容:
在这种情况下,它是
EjemploTres
具有命名函数的命名变量EjemploCuatro
在最后一种情况下,我们看到名称是如何对应的,
EjemploCuatro
而不是EjempoTres
因为这是函数的名称而不是变量的名称。这两种形式用于在 Javascript 中声明函数,不同之处不仅在于分配变量的方式,而且在使用一种或另一种方法声明它们时会产生语义后果。让我们按部分来:
这就是所谓的函数定义,用于声明函数并将其分配给标识符或变量
EjemploUno
。我还看到了用来指代它的术语函数声明。注意:此结构不需要
;
在其声明的末尾使用 a。以这种方式声明函数的结果是 Javascript 解释器在遇到类似情况时会提升变量并包含函数体。在以下代码片段中可以看到一个示例。
第一条指令
alert
引用了一个在下面 6 行代码中声明的变量,但是它向您显示了函数的内容(alert 内部使用 toString() 来显示您要表示的对象)但是第二alert
条指令显示undefined
发生了什么,因为声明了标识符,但没有为其分配任何值。当语句执行时,赋值只发生在下面的 9 行代码中Ejemplo2 = function()
第二种情况就是所谓的函数表达式,它可以是匿名的,也可以不是匿名的。两种形式都需要使用 a
;
将它们与下一条语句分开。例子:上面两种方式的区别在于,当变量
Ejemplo2
被赋值另一个值时,匿名函数会被垃圾回收器标记为移除,只要它没有被赋值到别处,因为没有变量在做它。参考所以它不可能再次找回它。在命名函数表达式的情况下,可以执行以下操作:
可以保存 MyFunc 标识符,即使将
Ejemplo2
其设置为其他值,您也可以继续引用该函数。这对于在其内部引用函数非常方便;例如,取消注册自身内部的事件,如以下代码片段所示:单击该按钮会删除该事件,因为存在对用于注册它的函数的引用。
这种模式的其他用途是,在出现异常的情况下,可以轻松识别问题的根源,因为函数名称将显示在错误堆栈上,并可用于创建递归。例子:
更新
还有一种情况差异会比较明显,那就是在严格模式下执行代码并且启用了 EcmaScript 5 时,它建立了一些要求,比如函数声明只能在上层块中使用,即,你不应该做这样的事情:
上面的代码在某些环境中不会产生错误,但这是因为浏览器对ECMA-262标准的扩展,该标准规定不能在任何地方使用函数声明 ,这一限制不适用于Expressions.of function。此链接包含有关该标准为何提出此类声明的信息。
更新 2
看到差异的最后一种情况是,在 Ecmascript 6 中已经存在块作用域,如果函数声明像前面的示例一样位于代码块内,则它会完全改变函数声明的语义。根据标准,这应该发生:
这仍处于实现过程中,但建议您不要编写可能被视为非法的代码,以便您编写的内容能够更好地在语言可能经历的未来变化中生存,因此重要的是您知道这两种结构的区别。
您的问题可以总结为从语言的角度来看它们完全不同(即使在规范中它们也分为http://es5.github.io/#x12.4和http://es5.github.io / #x13 ) 具有可用于声明函数的相似性。
这里
JavaScript 函数定义
解释你的意思
当你定义
您没有为函数定义名称,而是将其分配给变量,并通过它执行它。
当你做这样的事情时也是一样
在这种情况下,您将匿名函数作为参数传递。
命名函数:是那些在其声明中接收名称的函数。
表达式函数:它们的名称在声明中是可选的,如果没有,它们也称为匿名函数。
差异:
this
) 不同,它取决于它在哪里执行。例子:
执行结果将是:
常用匿名函数:
有用的例子(匿名函数)
练习:考虑到您有一个站点,您希望在其中列出每个已发布的图像,并且每次用户将鼠标悬停在控制台上时,其相应的编号都会显示在控制台中。
我们可以轻松地执行以下操作:
在上面的例子中,我们会得到一个意想不到的结果,因为它总是会为所有图像返回相同的索引(无论位置如何),并且这个数字将等于我们网站上图像的长度。虽然以下代码向我们展示了:
在这里,我们将得到预期的结果。
行为是由什么引起的?
在第一种情况下,变量
i
将通过修改其先前的值来增加,因此当mouseover
图像完成时,i
将使用循环中设置的最后一个值(在其最后一次迭代中)调用它。在第二种情况下(匿名自执行函数),我们可以看到它是
i
作为参数传递的,因此它作为一个新作用域被接收,直到它被内部修改为止,因此它对i
维护的引用收到时的值。首先,函数在运行时被分配给变量 foo(这是一个广泛用于指代任何名称被忽略的计算实体的通用术语)。
第二,函数在解析时被分配给标识符 foo。
参考
简而言之:ExampleOne 是一个声明函数,ExampleTwo 是一个表达函数。
这是什么意思?在执行代码之前,javascript 引擎会读取声明的函数,并且在执行代码之前不会读取表达的函数。
暗示?让我们看两个例子:
它会引发错误,因为 ExampleTwo 除了是一个函数之外,还是一个在这种情况下尚未声明的变量。