JavaScript:“function onload(){}”与“onload = function(){}”有什么不同?

时间:2009-11-30 08:22:46

标签: javascript scope

this question的答案中,我们读到function f() {}在本地定义名称,而[var] f = function() {}在全局定义名称。这对我来说很有意义,但是在两个声明之间存在一些不同的奇怪行为。

我用脚本

创建了一个HTML页面
onload = function() {
    alert("hello");
}

它按预期工作。当我把它改成

function onload() {
    alert("hello");
}
什么也没发生。 (Firefox仍然解雇了这个事件,但是WebKit,Opera和Internet Explorer没有,虽然坦率地说我不知道​​哪个是正确的。)

在这两种情况下(在所有浏览器中),我都可以验证window.onloadonload都已设置为该功能。在这两种情况下,全局对象this都设置为窗口,无论我如何编写声明,window对象都正在接收属性。

这里发生了什么?为什么一个声明的工作方式与另一个不同?这是JavaScript语言,DOM或两者之间的交互的一个怪癖吗?

6 个答案:

答案 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)

var onload = function() {
    alert("hello");
}

也会在当地宣布。

我建议你阅读这篇非常有用的文章:http://kangax.github.io/nfe/

答案 4 :(得分:0)

最简单的解释:

function aaaaaaa(){

可以在声明之前使用:

aaaaaaa();
function aaaaaaa(){

}

但这不起作用:

aaaaaaa();
aaaaaaa=function(){

}

那是因为在第三个代码中,您将aaaaaaa分配给匿名函数,而不是将其声明为函数。

答案 5 :(得分:-1)

这会产生错误:

foo();
var foo = function(){};

这不是:

foo();
function foo(){}

当您使用函数模块化和组织代码时,第二种语法更好,而第一种语法对于函数作为数据范例更好。