一、变量提升:你以为的代码顺序,其实是皇帝的新衣
JavaScript有个让人哭笑不得的"超能力"——变量提升。就像魔术师把兔子塞进帽子前,观众已经看到兔耳朵在晃动。当你在函数中间声明变量时,JavaScript引擎会自作主张地把声明提到最前面,但赋值操作却原地待命。这种"半吊子"提升经常导致新手在控制台看到undefined时一脸懵逼。
举个生活化的例子:你准备做西红柿炒蛋,先把锅烧热(执行上下文准备),这时候油瓶明明在橱柜最里面(代码后声明),但厨房已经默认油瓶存在于灶台上(变量提升)。当你伸手去拿油瓶时,油瓶确实存在(不会报错),但里面却空空如也(值为undefined),直到你真正走到橱柜前把油瓶拿过来(赋值操作),这时候才能开始倒油炒菜。
console.log(vegetable); // undefined 而不是报错
var vegetable = "西红柿";
要破解这个迷局,最简单的办法就是拥抱ES6的let和const,它们就像安装了GPS定位的智能油瓶,必须严格按顺序出现在正确位置,否则直接抛出错误提醒你:“主人,油瓶还在橱柜里呢!”
二、闭包:代码世界的"记忆面包"
闭包就像哆啦A梦的记忆面包,能让函数记住它出生时的环境。但这份"记忆"如果使用不当,轻则内存泄漏,重则引发玄学bug。想象你在咖啡馆点单,服务员(外层函数)给你一个定制马克杯(闭包),这个杯子永远记得你第一次点的咖啡口味(词法环境),哪怕咖啡馆打烊了(外层函数执行完毕),你还能用这个杯子喝到记忆中的味道。
function coffeeShop() {
let flavor = "卡布奇诺";
return {
getFlavor: () => flavor,
setFlavor: (newFlavor) => flavor = newFlavor
};
}
const myCup = coffeeShop();
console.log(myCup.getFlavor()); // 卡布奇诺
但要注意的是,如果滥用这种"记忆面包",你的程序内存会像贪吃蛇一样越来越胖。特别是在循环中创建闭包时,就像同时打开十个冰箱门却忘记关上,冷气(内存)会源源不断外泄。