1.引子
无意间在掘金上看到了一篇关于如何使用vue造轮子的框架, 里边有9到考察js和vue基础的题, 自己错了4道, 其中一道和箭头函数的this有关, 回头查了一下, 发现箭头函数的this总是指向词法作用域的, 遂写篇文章记录一下.
2.js作用域查找原理
js运行主要分为五部分: 1.编译 2.执行 3.查询 4.嵌套 5.异常
- 编译: 1.分词 - 词法单元 - 词法单元流数组 2.解析 - 抽象语法树(AST) 3.生成代码 - 生成机器指令
- 执行: 引擎寻找变量的过程 - 优先在当前作用域查找
- 查询: 分为LHS查询(查询变量, 赋值的左边)和RHS查询(查询赋值, 赋值的右边)
- 嵌套: 当前作用域查找不到, 则回去外层作用域查找, 直到全局作用域 -> 返回not define
- 异常: 如果LHS找不到, 就会返回not define
3.什么是词法
js的内部编译过程总共分3步
- 1.分词: 将字符组成的字符串, 分解成有意义的代码块, 这些代码块就叫 - 词法单元
// 词法分析后的结果[ "var" : "keyword", "a" : "identifier", "=" : "assignment", "2" : "integer", ";" : "eos" (end of statement)]复制代码
总结来说: 词法作用域就是块作用域
4.动态作用域
词法作用域实在书写代码时候就确定的, 而动态作用域不关心函数是在何处声明的, 只关心函数是在哪里调用的. 举例:
let a = 10function func1() { console.log(a)}function func2() { let a = 5 func1()}复制代码
上例中: 如果按词法作用域, 从func1里查找a, 没找到后, 去嵌套层查找, 找到最外层的a = 10 上例中: 动态作用域, 首先会在func1里查找a, 没找到后, 会顺着调用栈在func2中查找, 找到a = 5 *词法作用域是在赋值阶段确定, 动态作用域是在调用阶段确定