js中 var functionName = function() {} 和 function functionName() {} 两种函数声明的区别 (译)
stackOverflow中看到了很久以前问的一个关于函数声明的问题,问题对函数剖析的特别深。这里翻译了一下组织成一篇小博文,加深一下对这两种声明方式的印象。虽是老调重弹,但是只要能帮助理解问题,不管多老,都是好的。
| 问: |
js中有两种声明函数的方法,分别为:
var functionOne = function() {
// Some code
};
function functionTwo() {
// Some code
}
为什么会有两种不同的方法?每个方法的优点和缺点分别是什么?有什么情况是一种方法能完成而另外一种方法不能完成的吗?
| 答: |
by @Greg
不同点在于functionOne只会在到达赋值的那一行才会被真正定义,而functionTwo会在 包含它的函数或script脚本 执行的时候马上被定义。例如:
<script>
// Error undefined
functionOne(); var functionOne = function() {
}; // No error
functionOne();
</script> <script>
// No error
functionTwo(); function functionTwo() {
}
</script>
这也意味着你不能在条件语句中使用第二种方法定义函数:
<script>
if (test) {
// Error or misbehavior
function functionThree() { doSomething(); }
}
</script>
上面的例子无论test的值是真是假,实际上已经定义了functionThree函数。
by @Eugene Lazutkin
另外,也可以结合以上两种函数定义方法:
var xyz = function abc(){};
xyz 函数将会正常定义。而 abc 函数不会在浏览器中定义(除了IE浏览器),但是在其函数体内可见:
var xyz = function abc(){
// xyz is visible here
// abc is visible here
}
// xyz is visible here
// abc is undefined here
如果你想在所有浏览器中使用函数别名,可以使用这种声明方式:
function abc(){};
var xyz = abc;
这种情况下 xyz 和 abc 是同一个函数对象的别名:
console.log(xyz === abc); // prints "true"
使用第二种方式进行函数定义的一个说服性理由是,该函数对象有"name"属性(IE不支持)。当你定义一个类似下面的函数:
function abc(){};
console.log(abc.name); // prints "abc"
函数的name属性会被自动分配。但是当你以下面的方式定义函数:
var abc = function(){};
console.log(abc.name); // prints ""
它的name属性为空——这里创建了一个匿名函数,并将它赋值给其他变量。
推荐使用第二种函数定义方法的另一个理由是,可以用一个简短的内部名称来引用函数本身,同时为外部用户提供一个长的无冲突的别名:
// Assume really.long.external.scoped is {}
really.long.external.scoped.name = function shortcut(n){
// Let it call itself recursively: 循环调用其本身
shortcut(n - 1);
// ...
// Let is pass itself as a callback: 作为回调函数来传参
someFunction(shortcut);
// ...
}
在上面的例子中我们可以用一个外部声明来做和原函数相同的事,但是这样做不方便(同时太慢)。
(引用函数本身的其他方法是使用arguments.callee,这种方法比较常见<不知道这么翻译对不对>,并且在严格模式中不支持)。
实际上,javaScript对两种函数声明方法对待不同。这是一个函数声明:
function abc(){}
这里的abc在目前的范围中是处处都有定义的:
// We can call it here
abc(); // Works // Yet, it is defined down there.
function abc(){} // We can call it again
abc(); // Works
同样,它也会透过一个return语句被提前定义:
// We can call it here
abc(); // Works
return;
function abc(){}
另外一个函数表达式:
var xyz = function(){};
这里的xyz在声明行被定义:
// We can't call it here
xyz(); // UNDEFINED!!! // Now it is defined
xyz = function(){} // We can call it here
xyz(); // works
对函数(function)表达式和函数(Function)声明,我更倾向 "函数表达式" 声明(第一种方式),因为这种方式我可以控制可见性。当我定义这样一个函数:
var abc = function(){};
我知道我定义了一个局部函数。当我定义一个这样的函数:
abc = function(){};
我知道我定义了一个全局函数,并且我没有在作用域链的任何位置定义abc<不太清楚如何翻译>。然而像下面的定义方式:
function abc(){};
取决于上下文并且可能会让你猜测该函数真实定义的地方,特别是在使用eval()方法的时候——答案是:依赖于其所在的浏览器。
问题地址:http://stackoverflow.com/questions/336859/var-functionname-function-vs-function-functionname
翻译的不好,请勿拍!
js中 var functionName = function() {} 和 function functionName() {} 两种函数声明的区别 (译)的更多相关文章
- js中 var functionName = function() {} 和 function functionName() {} 两种函数声明的区别
js中有两种声明函数的方法,分别为: var functionOne = function() { // Some code }; function functionTwo() { // Some c ...
- JS中var声明与function声明两种函数声明方式的区别
JS中常见的两种函数声明(statement)方式有这两种: // 函数表达式(function expression) var h = function() { // h } // 函数声明(fun ...
- JS的两种函数声明方式的区别
---恢复内容开始--- js中常见的两种函数声明方式如下: // 函数表达式 var f = function() { console.log(1); } // 直接声明 function f () ...
- js中构造函数的原型添加成员的两种方式
首先,js中给原型对象添加属性和方法. 方式一:对象的动态特效 给原型对象添加成员 语法:构造函数.prototype.方法名=function (){ } 方式二:替换原型对象(不是覆盖,而是替换, ...
- JS中var声明与function声明以及构造函数声明方式的区别
JS中常见的三种函数声明(statement)方式有这三种: // 函数表达式(function expression) var h = function () { // h } // 函数声明(fu ...
- 【前端开发】】js中var写和不写的区别
js中var用与不用的区别 Javascript声明变量的时候,虽然用var关键字声明和不用关键字声明,很多时候运行并没有问题,但是这两种方式还是有区别的.可以正常运行的代码并不代表是合适的代码. v ...
- js中var的有或无--重复声明和以后的声明
js中var的有或无--重复声明和以后的声明 使用var语句多次声明一个变量不仅是合法的,而且也不会造成任何错误. 如果重复使用的一个声明有一个初始值,那么它担当的不过是一个赋值语句的角色. 如果重复 ...
- 浅谈JS中 var let const 变量声明
浅谈JS中 var let const 变量声明 用var来声明变量会出现的问题: 1. 允许重复的变量声明:导致数据被覆盖 2. 变量提升:怪异的数据访问.闭包问题 3. 全局变量挂载到全局对象:全 ...
- js函数表达式和函数声明的区别
我们已经知道,在任意代码片段外部添加包装函数,可以将内部的变量和函数定义"隐 藏"起来,外部作用域无法访问包装函数内部的任何内容. 例如: var a = 2; function ...
随机推荐
- web.xml 有什么用?(Java框架)
1.每个javaEE工程中都有web.xml文件,那么它的作用是什么呢?它是每个web.xml工程都必须的吗? 一个web中可以没有web.xml文件,也就是说,web.xml文件并不是web工程 ...
- ubuntu部署django详细教程
教程使用的软件版本:Ubuntu 18.04.1 LTS,django2.0,Python 3.6.5.nginx-1.13.7.uWSGI (2.0.17.1),Ubuntu是纯净的,全新的.下面我 ...
- jzoj4918. 【GDOI2017模拟12.9】最近公共祖先 (树链剖分+线段树)
题面 题解 首先,点变黑的过程是不可逆的,黑化了就再也洗不白了 其次,对于\(v\)的祖先\(rt\),\(rt\)能用来更新答案当且仅当\(sz_{rt}>sz_{x}\),其中\(sz\)表 ...
- js初识
01-Javascript简介 Web前端有三层: HTML:从语义的角度,描述页面结构 CSS:从审美的角度,描述样式(美化页面) JavaScript:从交互的角度,描述行为(提升用户体验) ...
- 用SQL玩转数据挖掘之MADlib(一)——安装
一.MADlib简介 MADlib是Pivotal公司与伯克利大学合作的一个开源机器学习库,提供了精确的数据并行实现.统计和机器学习方法对结构化和非结构化数据进行分析,主要目的是扩展数据库的分析能力, ...
- luogu4345 [SHOI2015]超能粒子炮·改(组合数/Lucas定理)
link 输入\(n,k\),求\(\sum_{i=0}^k{n\choose i}\)对2333取模,10万组询问,n,k<=1e18 注意到一个2333这个数字很小并且还是质数这一良好性质, ...
- luogu1556 幸福的路
注意到\(n\le10\),所以枚举经过的拐弯牛的所有排列. 注意到STL是一个好东西,所以我这里偷懒直接使用了next_permutation 枚举所有n的排列,对于每一个排列也就是经过拐弯牛的顺序 ...
- 在Mvc中,ExpandoObjec类的使用
创建一个基本mvc项目 1.向Models目录下添加一个类文件MyModel.cs文件,代码如下: using System; using System.Collections.Generic; us ...
- Qt 学习之路 2(7):MainWindow 简介
Qt 学习之路 2(7):MainWindow 简介 豆子 2012年8月29日 Qt 学习之路 2 29条评论 前面一篇大致介绍了 Qt 各个模块的相关内容,目的是对 Qt 框架有一个高屋建 ...
- FlowLayout(流式布局)用法
https://blog.csdn.net/liujun13579/article/details/7771191