刚写 JS 的新手,十有八九都被那些 “表面简单实际坑人” 的细节绊过跟头 —— 明明变量声明了却显示 undefined,this 指向一会儿是 window 一会儿是对象,数组遍历想中断却根本停不下来。这些问题真不是你不够细心,小索奇认为,JS 的 “坑” 大多藏在它的语言特性里,没吃透底层逻辑就容易踩雷,今天就扒几个最常见的雷点,全是能直接用的避坑干货。

第一个绕不开的坑就是 “变量提升”,简直是新手的 “入门杀”。是不是遇到过这种情况:先调用函数再声明,结果函数居然能正常执行;但先打印变量再声明,却显示 undefined?

这背后是 JS 的 “预编译” 机制在起作用。JS 引擎会在代码执行前,把 var 声明的变量和 function 声明的函数 “提前” 到当前作用域顶部 —— 但变量只是 “声明提升”,赋值还留在原地;函数则是 “声明 + 定义全提升”。比如 “console.log (a); var a = 1;”,实际执行顺序是 “var a; console.log (a); a = 1;”,所以会打印 undefined 而不是报错。

小索奇得提醒一句:现在写 JS 尽量用 let 和 const 代替 var,这俩不存在变量提升问题,还能避免变量重复声明的麻烦。如果非要用 var,就记住 “先声明再使用”,别跟 JS 的预编译机制较劲。

比变量提升更头疼的是 “this 指向”,堪称 JS 里的 “玄学难题”。同样一个 this,在对象方法里指向对象,在普通函数里指向 window,用 call 调用又指向传入的对象,新手根本摸不着头脑。

其实 this 的指向一点不玄,核心就一句话:“谁调用它,它就指向谁”。比如 obj.fn (),是 obj 调用 fn,this 就指向 obj;单独写 fn (),相当于 window.fn (),this 就指向 window;用 fn.call (obj2),是强制 obj2 调用 fn,this 就指向 obj2。

最容易出错的是箭头函数,它的 this 压根不按上面的规则来 —— 箭头函数没有自己的 this,它的 this 继承自外层作用域的 this。比如在对象里写 “fn: () => { console.log (this) }”,调用 obj.fn () 时,this 不会指向 obj,而是指向 obj 所在的外层作用域的 this。小索奇见过不少人用箭头函数写对象方法,结果因为 this 指向错了导致逻辑出错,这点一定要记牢。

还有个数组方法的坑,很多新手都栽过 —— 用 forEach 遍历数组时,想中途用 return 中断,结果发现根本没用,数组还是会遍历完。

这是因为 forEach 的设计逻辑就是 “遍历所有元素”,它里面的 return 只能跳出当前这一次循环,不能终止整个遍历。如果想中途中断,得用 for 循环或者 some、every 方法。比如用 some 方法,只要回调函数返回 true,就会立即终止遍历;every 方法则是返回 false 就终止。举个例子,找数组里第一个大于 10 的元素,用 some 比 forEach 靠谱多了,不会做无用的遍历。

另外,数组的 slice 和 splice 也经常被搞混,一个不小心就改乱原数组。slice 是 “切片”,接收 start 和 end 两个参数,返回新数组,不会改变原数组;splice 是 “剪接”,可以删除、插入元素,会直接修改原数组。比如 arr.slice (1,3),原数组不变;arr.splice (1,2),原数组直接少了两个元素。每次用这俩方法前,先想清楚 “要不要改原数组”,就能避免出错。

最后提个容易被忽略的点:“== 和 === 的区别”。新手总觉得俩都是判断相等,随便用,结果踩了大雷 —— 比如 0 == '' 会返回 true,0 === '' 却返回 false;null == undefined 是 true,null === undefined 却是 false。

说白了,== 会做 “隐式类型转换”,先把两边的值转成同一类型再比较;=== 则是 “严格相等”,既比较值也比较类型,不做任何转换。实际开发中,除了判断 null == undefined 这种特殊场景,其他时候尽量用 ===,能避免很多因为类型转换带来的诡异 bug。小索奇写代码时,除非有明确理由,否则一律用 ===,省心又靠谱。

JS 的这些坑看似杂乱,其实都是对语言特性理解不到位导致的。踩坑不可怕,关键是搞懂背后的逻辑,下次就不会再犯。你写 JS 时最头疼的是 this 指向、变量提升还是数组方法?评论区聊聊,让更多新手少走弯路。

我是【即兴小索奇】,点击关注,后台回复 领取,获取更多相关资源