最近在看《你不知道的JavaScript》,Mark一下。
一. LHS(Left-Hand-Side)查询和RHS(Right-Hand-Side)查询
问题1:之前只知道在JavaScript中,如果一个变量a未经声明就直接取值,如 console.log(a),会抛出ReferenceError异常;如果一个变量a未经声明,就直接赋值,如 a = 2,那么程序会自动创建一个全局变量a,然后再把2赋给a,但是这是为什么呢?
如 var a = 2,在JavaScript预编译结束后引擎开始执行代码,引擎执行它时,会通过查找变量a来判断它是否已声明过,查找的过程由作用域进行协助。有两种查询类型,LHS(Left-Hand-Side)查询和RHS(Right-Hand-Side)查询。
作用域是一套规则,用于确定在何处以及如何查找变量(标识符)。如果查找的目的是对变量进行赋值,那么就会使用LHS查询,如 a = 2;如果目的是获取变量的值,那么就会使用RHS查询,如 console.log(a)。非严格模式下,不成功的RHS引用(如找不到变量a)会导致抛出ReferenceError异常;不成功的LHS引用(如找不到变量a)会导致自动隐式地创建一个全局变量(a),该变量使用LHS引用的目标作为标识符,但严格模式下也会抛出ReferenceError异常。
赋值操作符会导致LHS查询,= 操作符或调用函数时传入参数的操作都会导致关联作用域的赋值操作。
LHS查询和RHS查询都会在当前执行作用域中开始,如果有需要(没找到),就会向上一级作用域继续查找目标标识符,这样每次上升一级作用域,最后抵达全局作用域,无论找到或者没找到都将停止。
二. 区分函数声明和函数表达式
区分函数声明和函数表达式最简单的方法是看function关键字出现在声明中的位置(不仅仅是一行代码,而是整个声明中的位置)。如果function是声明中的第一个词,那么就是一个函数声明,否则就是一个函数表达式。