我知道有几种方法可以在JavaScript中定义一个函数。其中两个最常见的是:
(1) function add (a, b) {
return a + b;
}
(2) var add = function (a, b) {
return a + b;
}
我觉得将函数作为一个对象的想法可以像任何其他变量一样传递。所以我完全理解(2)
正在做什么。它正在创建一个函数并分配给add
(假设这是在全局范围内,因此add
是一个全局变量)所述函数。但是如果我使用(1)
而发生了什么呢?我已经知道它在执行顺序上有所不同:如果我使用(1)
,那么我可以在代码中定义add()
的点之前引用add()
,但是如果我使用{ {1}}然后我必须先将我的功能分配给(2)
,然后再开始引用add
。
add()
只是(1)
的一个快捷方式,虽然它恰好像其他C风格的语言一样,允许我们定义一个“低于”它使用点的函数吗?或者它内部是一种不同类型的功能?哪个更符合JavaScript的“精神”(如果这个术语不是太模糊)?你会把自己限制在一个或另一个,如果是这样的话吗?
答案 0 :(得分:6)
看起来您已经了解 function declarations 1 (1)和 function expressions (2)。另请注意,在(1)中仍然存在一个名为add
的局部变量,其中包含一个函数值,就像在(2)中一样:
function hello () {
alert('Hello World');
}
console.log(typeof hello); // prints "function"
setTimeout(hello, 1000); // you can still pass functions around as arguments,
// even when using function declarations.
值得一提的另一点是函数声明(1)不应该用于有条件地定义函数(例如在if
语句中),因为正如您所提到的,它们是由JavaScript解释器 2 自动移动到包含范围的顶部。这通常称为 hoisting 。
至于哪种方法更符合JavaScript的精神,我更喜欢使用函数表达式(2)。对于更权威的意见,Douglas Crockford列出了他的流行The Good Parts book 2 的“坏部分”章节中的函数声明(1)。
1 也称为函数语句(参见下面的@Tim Down's条评论)。
2 实际上有些浏览器能够在if
语句中处理函数声明(再次参考下面的评论)。
3 JavaScript: The Good Parts - 附录B:第113页。
答案 1 :(得分:2)
function foo() {};
foo.toString() //-> "function foo() {}"
var bar = foo;
bar.toString() //-> "function foo() {}"
因此它声明了一个命名函数。无论变量指向哪个变量,都会保留其名称。使用另一种语法是匿名函数,它是无名的,只有在变量引用时才能被访问。
var foo = function() {};
foo.toString() //-> "function () {}"
var bar = foo;
bar.toString() //-> "function () {}"
就使用哪种风格而言,没有主要规则。虽然我个人赞成匿名语法,因为它提醒我函数确实是可以传递的对象。我也倾向于赞成“它只是一个大主对象”的方法,这要求以这种方式声明函数。
var MyThingy = {
foo: function() { alert('foo') },
bar: function() { MyThingy.foo() }
}
但是在创建函数之后,差异并不重要且行为相同。但是匿名语法在你提到的魔术之前的扫描量较少,而且复杂代码和奇怪的作用域情况下的错误更少。