为啥正文中的 javascript 函数优先于头部中的函数?
Posted
技术标签:
【中文标题】为啥正文中的 javascript 函数优先于头部中的函数?【英文标题】:Why javascript function in the body takes precedence over function in the head?为什么正文中的 javascript 函数优先于头部中的函数? 【发布时间】:2018-06-03 04:49:47 【问题描述】:我试图了解 javascript 中的执行顺序。为什么body中的foo优先于head中的foo。不是先编译的head里的foo吗?
<head>
<meta charset="UTF-8">
<title>Hello</title>
<script type="text/javascript">
function foo()
greeting = "hello from the head";
alert(greeting);
</script>
</head>
<body>
<div id="clickMe" onclick="foo()">Click me</div>
<script>
function foo()
greeting = "hello from the body";
alert(greeting);
</script>
</body>
</html>
【问题讨论】:
【参考方案1】:以后的函数声明会覆盖旧的函数声明。在新函数被声明之前,旧函数仍然可以被调用:
<script type="text/javascript">
function foo()
greeting = "hello from the head";
alert(greeting);
foo();
</script>
<div id="clickMe" onclick="foo()">Click me</div>
<script>
function foo()
greeting = "hello from the body";
alert(greeting);
</script>
但是一旦较低的脚本标签运行,函数名就会被重新分配。如果你这样看可能更有意义,每个函数都重新分配window.foo
:
<script type="text/javascript">
window.foo = function foo()
greeting = "hello from the head";
alert(greeting);
</script>
<div id="clickMe" onclick="window.foo()">Click me</div>
<script>
window.foo = function foo()
greeting = "hello from the body";
alert(greeting);
</script>
【讨论】:
Javascript 未被解释。它有一个运行时编译器。【参考方案2】:这与两次声明同一个函数没有什么不同
function foo()
console.log("first");
function foo()
console.log("second");
foo(); // prints "second"
这在某种程度上与此没有什么不同
let bar;
bar = 1;
bar = 2;
bar
现在是2
。
您可以通过使用不同的语法来避免这种情况
const foo = () =>
console.log("first");
;
const foo = () =>
console.log("second");
;
在这种情况下你会得到一个错误
Uncaught SyntaxError: Identifier 'foo' has already been declared
而且似乎可以跨脚本工作
<script>
const foo = () =>
console.log("first");
;
</script>
<script>
const foo = () =>
console.log("second");
;
</script>
【讨论】:
【参考方案3】:这就是所谓的影子。
JS 编译器提升脚本中的函数。后面的会用相同的名字覆盖前面的遭遇。
function foo()
console.log('Foo early');
function foo()
console.log('Foo late');
foo(); //Foo leate
【讨论】:
这不是阴影。不同之处在于阴影意味着仍然存在对原始定义的引用。 阴影如何引用原始定义?能举个例子吗?var array = []; array.map = () => ; array.map(); /* returns undefined */ delete array.map; array.map(() => ); /* returns array */
这使用原型链来隐藏 map()
的定义。在HTMLInputElement
上使用具有相同名称的 DOM 元素属性和属性时存在类似的示例,例如 value
。
那是属性阴影。虽然这是真的,但它并没有使 OP 的案例不被遮蔽。后面的声明会影响前面的提升函数。
“属性阴影”,不管你喜欢怎么称呼它,仍然存在于***函数声明中,它只是window
的一个自己的属性。例如function addEventListener ()
会影响window.addEventListener
,因为它不是window
自己的属性,但function prompt ()
会覆盖window.prompt
,因为它是 window
的自己的属性【参考方案4】:
基本上只是因为主体中的那个是它读取的最后一个函数,所以它只是坚持下去。
记住 HTML 文档是从上到下读取的,所以如果你有两个相同函数的实例,它实际上会保留最接近文档末尾的那个
【讨论】:
以上是关于为啥正文中的 javascript 函数优先于头部中的函数?的主要内容,如果未能解决你的问题,请参考以下文章