企业🤖AI智能体构建引擎,智能编排和调试,一键部署,支持私有化部署方案 广告
# NO.1 ``` var c = 1; function c(c) { console.log(c); var c = 3; } c(2) ``` ## 技术点: 1.变量提升 2.函数提升 3.预处理 4.调用顺序** ## 陷阱 全局变量名、函数名、函数形参都是`c`** ## 结果 ![](https://box.kancloud.cn/04d0bce3c1a3555d18b8160c65faba6f_217x27.png) ## 分析 看到这结果有没有大吃一惊? 我们现在来分析下原因。 这里我们先来了解下“预处理”,那什么是预处理呢?js语言本身具有预处理机制,js引擎在预处理期对所有声明的变量和函数进行处理,就是先把变量进行声明并读到内存里。也就是收集用var声明的变量信息和函数声明信息 还有一点是预处理时,变量和函数的优先顺序,先变量后函数。当变量名和函数名一致时后者会覆盖前者,我们看下下面的小案例: ``` function b() {} var b console.log(typeof b) ``` 结果为function,这就证实了,我们刚才的结论,执行顺序先变量后函数,变量名一致时,函数就会覆盖变量。 再来说一下预处理,看一下下面的小案例: ``` var a = 2 function fn() { console.log(a) var a = 3 } fn() ``` 运行下,结果为undefined。 为什么为undefined呢?因为这里预处理顺序是这样的,外面声明了个全局变量a,值为2,但是里面把a声明成了局部变量,函数内部的预处理顺序为先声明var a;然后console.log(a);最后a=3;所以我们调用函数的时候,里面是有a,所以不会调外面的全局a,只是里面的a暂时还没有值,因为a=3这赋值步骤是在console.log(a)后面执行的,所以我们运行时就看到undefined了。拓展下,如果函数里面去掉var,那么打印出来的值就是2了,然后全局变量a又被赋值为3。 那好,我们现在回到我们刚才的题目上来,刚才题目的解析顺序可以理解为以下步骤: 1. 首先预处理 `var c` 2. 然后预处理整个c函数 ``` function c(c) { console.log(c); var c = 3; } ``` 此时`c`的`typeof`为`function` 3. 接着给`c`赋值为`1`,即 `c=1` 此时`c`是整型变量`1`。`typeof`为`number`了 4. 最后再执行`c(2)`调用函数 所以我们调用的时候当然就会报`c`不是一个函数的错误了,因为他现在是一个整型变量了啊,哈哈,是不是很伤脑筋啊…… # NO.2 ``` var a = 6 setTimeout(function () { console.log(0) alert(a) a = 666 }, 0) console.log(1) a = 66 ``` ## 技术点 定时器、意外全局变量、作用于与作用域链、变量查找、事件循环 ## 结果 1 0 66 ## 分析 按照先执行同步代码原则,即使setTimeout的时间是0甚至是不传时间,setTimeout仍然是异步代码 * 首先输出:1 * 然后将66赋值给全局变量a,此时全局变量a = 66 * 接着执行异步setTimeout中的代码,输出:0 * 最后弹出变量a,此时变量a的值是66