在this question的答案中,我们读到function f() {}
在本地定义名称,而[var] f = function() {}
在全局定义名称。这对我来说很有意义,但是在两个声明之间存在一些不同的奇怪行为。
我用脚本
创建了一个HTML页面onload = function() {
alert("hello");
}
它按预期工作。当我把它改成
function onload() {
alert("hello");
}
什么也没发生。 (Firefox仍然解雇了这个事件,但是WebKit,Opera和Internet Explorer没有,虽然坦率地说我不知道哪个是正确的。)
在这两种情况下(在所有浏览器中),我都可以验证window.onload
和onload
都已设置为该功能。在这两种情况下,全局对象this
都设置为窗口,无论我如何编写声明,window
对象都正在接收属性。
这里发生了什么?为什么一个声明的工作方式与另一个不同?这是JavaScript语言,DOM或两者之间的交互的一个怪癖吗?
答案 0 :(得分:4)
很多人都正确地指出了全球/本地之间的区别(更新:这些答案现在大多已被作者删除)
var x = function() {
和
function x() {
但实际上并没有回答你的具体问题,因为你实际上并没有做第一个问题。
您的示例中两者之间的区别是:
// Adds a function to the onload event
onload = function() {
alert("hello");
}
尽管
// Declares a new function called "onload"
function onload() {
alert("hello");
}
答案 1 :(得分:4)
这两个片段在当前作用域中声明了一个名为“onload”的函数。没有绑定。
function onload() { ... }
var onload = function() { ... }
此代码段将函数分配给当前范围上名为“onload”的属性/变量/字段:
onload = function() { ... }
Firefox执行绑定并在第一个片段上引发onload事件的原因可能是因为Firefox chrome(其用户界面)本身是使用JavaScript编写和自动化的 - 这就是为什么它如此灵活,易于编写扩展名。不知何故,当你以这种方式声明本地范围的onload
函数时,Firefox“替换了”window
(当时很可能是当地的上下文)onload
的实现(在那里)当其他浏览器正确地将声明“沙箱化”到另一个范围(例如,global
或其他)时,时间,空函数或未定义)。
答案 2 :(得分:1)
根据Tim Down的有用评论以及与Jonathan Penn的简短讨论,以下是我的想法:
当JavaScript解释器分配给window.onload
属性时,它正在与浏览器提供的对象进行通信。它调用的setter注意到该属性被称为onload
,因此转到浏览器的其余部分并连接相应的事件。所有这些都超出了JavaScript的范围 - 脚本只看到已经设置了属性。
当您编写声明function onload() {}
时,不会以完全相同的方式调用setter。由于声明导致赋值发生在 parse 时间,而不是评估时间,因此脚本解释器继续并在不告知浏览器的情况下创建变量;否则窗口对象尚未准备好接收事件。无论是什么,浏览器都没有机会像编写onload = function() {}
时那样看到分配,这通过了正常的setter例程。
答案 3 :(得分:0)
答案 4 :(得分:0)
最简单的解释:
function aaaaaaa(){
可以在声明之前使用:
aaaaaaa();
function aaaaaaa(){
}
但这不起作用:
aaaaaaa();
aaaaaaa=function(){
}
那是因为在第三个代码中,您将aaaaaaa分配给匿名函数,而不是将其声明为函数。
答案 5 :(得分:-1)
这会产生错误:
foo();
var foo = function(){};
这不是:
foo();
function foo(){}
当您使用函数模块化和组织代码时,第二种语法更好,而第一种语法对于函数作为数据范例更好。