为什么在Javascript中定义函数之前可以使用它?
此代码始终可以在各个浏览器中运行:
function fooCheck() { alert(internalFoo()); return internalFoo(); function internalFoo() { return true; } } fooCheck();
虽然我找不到一个为什么它应该工作的单一的参考。 我在John Resig的演讲笔记中首先看到了这一点,但只是提到了这一点。 对于这个问题,没有任何解释。
有人请赐教吗?
function
声明是神奇的,并且使其标识符在其代码块*中的任何内容被执行之前被绑定。 这不同于以正常自上而下的顺序评估的function
expression式的赋值,所以如果您将示例更改为:
var internalFoo = function() { return true; };
它会停止工作。 函数声明在语法上与函数expression式完全分离,即使它们看起来几乎相同,并且在某些情况下可能不明确。
这在ECMAScript标准10.1.3节中有logging。 不幸的是,ECMA-262即使是标准的标准也不是一个非常易读的文件!
*:包含function,块,模块或脚本。
浏览器从头到尾读取您的html,并且可以在读取并分析为可执行块(variables声明,函数定义等)时执行它。但是在任何时候,只能使用html之前定义的内容。
这与处理(编译)所有源代码的其他编程上下文不同,将它与所需的任何库链接在一起,并构build一个可执行模块,此时执行开始。
您可以定义引用项目(variables,其他函数等等)的函数,这些函数是在进一步定义的基础上进行的,但是只有所有函数都可用时,才能执行这些函数。
随着您熟悉JavaScript,您将会深刻地意识到您需要按照正确的顺序编写代码。
修订:要确认接受的答案(上面),请使用Firebug来浏览网页的脚本部分。 你会看到它从函数跳到函数,在实际执行任何代码之前只访问第一行。
它被称为HOISTING – 在被定义之前调用(调用)一个函数。
我想要写的两种不同types的函数是:
expression式函数和减速函数
1-expression式函数:函数expression式可以存储在一个variables中,所以它们不需要函数名。它们也将被命名为匿名函数(一个没有名字的函数)。 要调用(调用)它们总是需要使用variables名称 。如果调用之前的调用(这意味着在此处没有提升),则这些types的函数将不起作用。 我们总是必须先定义expression式函数然后调用它。
let lastName = function (family) { console.log("My last name is " + family); }; let x = lastName("Lopez");
这是你可以写在ES6中的方法:
lastName =(family)=> console.log(“我的姓氏是”+ family);
x = lastName(“Lopez”);
2-减速函数:使用以下语法声明函数不会立即执行。 它们被“保存以供以后使用”,并且当它们被调用(被调用)时将在稍后被执行。如果在它们被定义之前或之后调用它们,则这些types的function起作用。 如果在定义之前调用减速function – 起升 – 正常工作。
function Name(name) { console.log("My cat's name is " + name); } Name("Chloe");
举例:
Name("Chloe"); function Name(name) { console.log("My cat's name is " + name); }
我只使用JavaScript一点。 我不确定这是否会有所帮助,但看起来与您正在谈论的内容非常相似,可能会提供一些见解:
http://www.dustindiaz.com/javascript-function-declaration-ambiguity/
有些语言要求在使用之前必须定义标识符。 原因是编译器在源代码上使用了单个传递。
但是,如果有多个通行证(或一些支票被推迟),你可以完全没有这个要求生活。 在这种情况下,代码可能首先被读取(并解释),然后链接被设置。
函数“internalFoo”的主体需要在parsing时到达某处,所以当JS解释器读取代码(又称parsing)时,会创build该函数的数据结构并分配名称。
之后才运行代码,JavaScript实际上试图找出“internalFoo”是否存在,它是什么以及是否可以调用等等。
出于同样的原因,以下将始终将foo
放在全局名称空间中:
if (test condition) { var foo; }