我是Javascript的新手,对函数声明的工作原理感到困惑。我对此做了一些测试并得到了一些有趣的结果:
say();
function say()
{
alert("say");
}
前方声明工作和弹出“说”
相反
say();
say = function()
{
alert("say");
}
没有用,虽然它也声明了一个函数对象
如果我们宣布该函数并在之后重新声明:
function say()
{
alert("speak");
}
say();
function say()
{
alert("say");
}
我说“说”而不是“说话”。这太令人惊讶了!
行。似乎只有最新的函数声明才有效。然后让我们首先声明函数对象,然后是“常规”函数:
say = function()
{
alert("speak");
}
say();
function say()
{
alert("say");
}
say();
另一个惊喜,是“说话”,然后是“说话”。 “常规”函数声明根本不起作用!
对所有这些都有解释吗?并且,如果“常规”函数声明真的是“脆弱的”并且可以通过具有相同名称的函数对象轻松覆盖,那么我应该远离它吗?
另一个问题是:只使用函数对象格式,前向声明是否变得不可能?有没有办法在Javascript中“模拟”它?
答案 0 :(得分:3)
Javascript的工作原理如下:
解析文档,并在执行实际语句之前立即考虑function
声明。这解释了你的第一个例子。
如果将一个函数分配给局部变量,那么在执行期间就完成了,所以你不能在第二个例子中使用该方法。
您遇到的情况是,如果您声明一个函数两次,则最后一个将由整个应用程序使用。那是你的第三个例子。
这些函数是window
对象的成员,它们实际上是全局声明的。如果将局部变量分配给函数的值,则该局部变量优先于window
对象中的成员。如果javascript找不到局部变量,它会在范围内搜索以找到它,window
对象是最后的手段。这就是你上一个例子中发生的事情,它有一个变量say
,其范围比全局函数say
更具体。
如果您在运行时重新声明say
,即在上一个示例中交换声明的顺序,那么您会看到两个不同的警报:
say(); //speak, the global function
function say() {
alert('speak');
}
var say = function() {
alert('say');
}
say(); //say, the declared local variable
答案 1 :(得分:1)
say();
function say()
{
alert("say");
}
这里解释器在调用时获取say()
的定义,然后执行它。
say();
say = function()
{
alert("say");
}
这里没有要获取say()
的定义 - 而是要为变量分配匿名函数。解释器无法“找到”它,就像它可以找到前向声明一样。
function say()
{
alert("speak");
}
say();
function say()
{
alert("say");
}
此处say
已定义,然后重新定义 - 最后一个定义胜出。
say = function()
{
alert("speak");
}
say();
function say()
{
alert("say");
}
say();
这里say
是一个指向匿名函数的变量(在解释第一个语句之后)。这优先于任何函数定义,就像在赋值之前放置函数定义一样。
但如果你有
say();
say = function()
{
alert("speak");
}
say();
function say()
{
alert("say");
}
然后你会得到“说”然后“说”。
答案 2 :(得分:0)
您可以期望按顺序应用函数定义。然后将按顺序执行所有非方法代码行,包括函数对象的赋值。这解释了您的每个示例。这是一个有趣的问题。在尝试调用它之后,你真的无法分配一个函数对象,并期望它能够工作。但是,实际上将首先应用遵循可执行代码的函数定义。
答案 3 :(得分:0)
稍后调用该函数总是好主意,即使javascript就是这样。
大多数语言都不会这样做,而是这样做。
function say(){
alert("say");
}
say();
或
say = function(){
alert("say");
}
say();
或
(function(){
alert("say");
})();