5 回答
TA贡献1784条经验 获得超7个赞
不同之处在于它functionOne
是一个函数表达式,因此只在到达该行时定义,而是functionTwo
一个函数声明,并且只要执行其周围的函数或脚本(由于提升)就会定义。
例如,一个函数表达式:
// TypeError: functionOne is not a function
functionOne();
var functionOne = function() {
console.log("Hello!");
};
并且,一个函数声明:
// Outputs: "Hello!"
functionTwo();
function functionTwo() {
console.log("Hello!");
}
这也意味着您无法使用函数声明有条件地定义函数:
if (test) {
// Error or misbehavior
function functionThree() { doSomething(); }
}
上面的实际定义functionThree与... test的值无关 - 除非use strict有效,否则它只会引发错误。
TA贡献1744条经验 获得超4个赞
说到全局上下文,var
语句和FunctionDeclaration
最后都将在全局对象上创建一个不可删除的属性,但两者的值都可以被覆盖。
两种方式之间的细微差别在于,当变量实例化过程运行时(在实际代码执行之前),所有声明的标识符var
都将被初始化undefined
,并且FunctionDeclaration
自那时起使用的标识符将可用,例如:
alert(typeof foo); // 'function', it's already available
alert(typeof bar); // 'undefined'
function foo () {}
var bar = function () {};
alert(typeof bar); // 'function'
分配bar FunctionExpression发生在运行时间。
由a创建的全局属性FunctionDeclaration可以像变量值一样被覆盖而没有任何问题,例如:
function test () {}
test = null;
您的两个示例之间的另一个明显区别是第一个函数没有名称,但第二个函数有它,这在调试(即检查调用堆栈)时非常有用。
关于您编辑的第一个示例(foo = function() { alert('hello!'); };),这是一个未声明的作业,我强烈建议您始终使用该var关键字。
使用赋值,如果没有var
语句,如果在作用域链中找不到引用的标识符,它将成为全局对象的可删除属性。
此外,未声明的作业ReferenceError
在严格模式下投入ECMAScript 5 。
必读:
TA贡献1796条经验 获得超4个赞
您在那里发布的两个代码段几乎在所有目的下都会以相同的方式运行。
但是,行为的差异在于使用第一个variant(var functionOne = function() {}
),该函数只能在代码中的该点之后调用。
使用第二个variant(function functionTwo()
),该函数可用于在声明函数的上方运行的代码。
这是因为对于第一个变体,函数foo
在运行时分配给变量。在第二个中,foo
在解析时将该函数分配给该标识符。
更多技术信息
JavaScript有三种定义函数的方法。
您的第一个代码段显示了一个函数表达式。这涉及使用“function”运算符来创建函数 - 该运算符的结果可以存储在任何变量或对象属性中。函数表达式就是这样强大的。函数表达式通常称为“匿名函数”,因为它不必具有名称,
你的第二个例子是函数声明。这使用“function”语句来创建函数。该函数在分析时可用,并且可以在该范围内的任何位置调用。您以后仍可以将其存储在变量或对象属性中。
定义函数的第三种方法是“Function()”构造函数,它在原始帖子中没有显示。不建议使用它,因为它的工作方式与
eval()
存在问题的方式相同。
添加回答
举报