JavaScript中同一函数多次定义为何最后一次实现优先,能否修改该默认行为?
问题解答
JS引擎的处理逻辑
这个现象是JavaScript的函数声明提升规则和同名声明覆盖机制共同导致的:
- 你代码中多次用
function myFunction()的形式做全局函数声明,JS引擎在预编译阶段会把所有全局函数声明提前到作用域顶部处理 - 同一作用域下重复声明同名函数时,后面的声明会直接覆盖前面的函数引用,所以所有预编译逻辑执行完成后,全局的
myFunction指向的就是最后一次声明的第四版实现 - 按钮的
onclick事件触发时会去全局作用域查找myFunction,自然每次都执行最后一次定义的逻辑。
覆盖默认行为的实现方法
完全可以修改这种默认行为,常用的实现方案有以下几种:
1. 用不同变量存储各版本函数,明确绑定指定实现
放弃重复声明同名函数,将不同的逻辑分别赋值给不同变量,绑定事件时直接指定要使用的版本即可:
<!DOCTYPE html> <html> <body> <h2>JavaScript in Body</h2> <p id="demo">A Paragraph.</p> <button type="button" id="btn">Try it</button> <script> const func1 = function() { document.getElementById("demo").innerHTML = "FIRST: Paragraph changed."; } const func2 = function() { document.getElementById("demo").innerHTML = "SECOND: Paragraph changed."; } const func3 = function() { document.getElementById("demo").innerHTML = "THIRD: Paragraph changed."; } const func4 = function() { document.getElementById("demo").innerHTML = "FOURTH: Paragraph changed."; } // 此处可按需切换绑定的函数版本,比如要绑定第一个版本就传func1 document.getElementById('btn').addEventListener('click', func1); </script> </body> </html>
2. 用闭包存储多版本逻辑,支持按顺序切换执行
如果需要每次点击按顺序调用不同版本的逻辑,可以用闭包缓存所有实现和调用计数:
<!DOCTYPE html> <html> <body> <h2>JavaScript in Body</h2> <p id="demo">A Paragraph.</p> <button type="button" onclick="myFunction()">Try it</button> <script> const myFunction = (function() { // 存储所有版本的逻辑 const versions = [ () => document.getElementById("demo").innerHTML = "FIRST: Paragraph changed.", () => document.getElementById("demo").innerHTML = "SECOND: Paragraph changed.", () => document.getElementById("demo").innerHTML = "THIRD: Paragraph changed.", () => document.getElementById("demo").innerHTML = "FOURTH: Paragraph changed." ]; // 调用计数 let invokeCount = 0; return function() { versions[invokeCount % versions.length](); invokeCount++; }; })(); </script> </body> </html>
3. 块级作用域隔离同名函数
如果必须使用同名的函数声明,可以开启严格模式,将不同版本的函数放到独立的块级作用域中,避免全局作用域下的覆盖:
'use strict'; { function myFunction() { console.log('第一个版本'); } // 这个作用域内调用myFunction就是第一个版本 } { function myFunction() { console.log('第二个版本'); } // 这个作用域内调用myFunction就是第二个版本 }
内容的提问来源于stack exchange,提问作者Sharad Nanda
相关产品推荐
相关产品推荐

