使用let/const替代var定义闭包时出现重复声明错误的原因
关于let/const替换var后触发重复声明错误的问题解析
问题场景
使用var定义的闭包代码可正常运行,但将代码中的var替换为let或const后,触发了重复声明的语法错误。
原可运行代码(var版本)
// Define the closure var rentPrice = function (initialRent) { var rent = initialRent; // Define private variables for // the closure return { getRent: function () { return console.log(rent); }, incRent: function (amount) { rent += amount; console.log(rent); }, decRent: function (amount) { rent -= amount; console.log(rent); }, }; }; var Rent = rentPrice(8000); // Access the private methods Rent.incRent(2000); Rent.decRent(1500); Rent.decRent(1000); Rent.incRent(2000); Rent.getRent();
报错信息
VM1926:1 Uncaught SyntaxError: Identifier 'rentPrice' has already been declared
修改后的代码(let版本)
// Define the closure let rentPrice = function (initialRent) { let rent = initialRent; // Define private variables for // the closure return { getRent: function () { return console.log(rent); }, incRent: function (amount) { rent += amount; console.log(rent); }, decRent: function (amount) { rent -= amount; console.log(rent); }, }; }; let Rent = rentPrice(8000); // Access the private methods Rent.incRent(2000); Rent.decRent(1500); Rent.decRent(1000); Rent.incRent(2000); Rent.getRent();
核心疑问
并未重复声明rentPrice变量,只是调用该函数并将结果存入Rent变量,为何会触发重复声明的语法错误?
问题原因与解决方案
- 变量声明规则差异:
var存在变量提升特性,且允许在同一作用域内重复声明同名变量;而let/const遵循块级作用域规则,同一作用域中不允许重复声明同名标识符。 - 实际触发场景:你大概率是在同一个作用域(比如浏览器控制台、同一个脚本文件)中多次运行了这段代码。第一次运行时
let rentPrice已经完成声明,第二次运行时再次执行let rentPrice就会触发语法错误——而var因为允许重复声明,多次运行不会报错。 - 解决办法:
- 若在浏览器控制台测试,每次运行前可通过
delete window.rentPrice清除全局作用域中的变量,或者开启控制台的「隔离上下文」模式,避免变量残留。 - 若在脚本文件中,确保代码只执行一次,或者将代码包裹在立即执行函数表达式(IIFE)中,形成独立作用域隔离全局变量:
(function() { let rentPrice = function (initialRent) { let rent = initialRent; return { getRent: function () { return console.log(rent); }, incRent: function (amount) { rent += amount; console.log(rent); }, decRent: function (amount) { rent -= amount; console.log(rent); }, }; }; let Rent = rentPrice(8000); Rent.incRent(2000); Rent.decRent(1500); Rent.decRent(1000); Rent.incRent(2000); Rent.getRent(); })();
- 若在浏览器控制台测试,每次运行前可通过
内容的提问来源于stack exchange,提问作者Sachin
相关产品推荐
相关产品推荐

