1.变量与函数的定义
变量:var a; //定义变量a
var a = 123; //定义变量a,并且赋值为123
js中的变量是若类型的,变量占用固定内存空间,因此是直接量
函数:function fn (传参){函数体} //声明函数fn(“定义式函数”,即函数声明)
var a = function(传参){函数体} ; //先定义变量a与一个匿名函数,并将匿名函数赋值给变量a(赋值式,即函数表达式)
2.定义的作用
变量的定义指明了变量的作用域
函数的定义指明了函数的作用域,同时定义了函数体结构
3.预解析
在页面加载的时候,浏览器加载JS文件并扫描代码,此过程中,函数声明与变量定义会被预处理,即提升至其作用域顶部先进行声明,对于函数,声明了函数名与函数体,对于变量声明了变量名,并不赋值。因此,定义式函数可在其函数代码前被调用,而函数表达式不行,变量在这种情况下为undefined。
这种预解析也称函数声明提升与变量提升,此时后定义的变量无法覆盖同名函数的定义。
4.作用域
上面介绍了函数声明与变量声明都指明了作用域,JS的作用域按函数来划分,在JS中没有所谓的块作用域,即for,if,which,switch等流程控制语句是没有限定作用域的作用的。在函数中由var定义的变量为局部变量,只在该函数内生效,函数中的函数也为该作用域中的函数,函数外无法直接调用,可以通过return间接与外部沟通,这里就涉及了闭包的知识。可以将作用域比做房间,而全局环境比做房子,函数在执行时,先使用自己房子内的资源,当搜索不到相关资源时,才开房门到外层空间去搜寻,直至找到并返回资源,若直至跑到客厅(全局)去找资源,依旧找不到,则报错,若是在此过程中找到变量但未赋值,则返回undefined。同时对兄弟房间的搜寻是不允许的。
这样的一层一层作用域相连,形成作用域链。
5.JS的执行
浏览器在对JS预解析后,开始由上到下执行JS,赋值操作是在顺序执行时进行赋值的,后赋值的会覆盖先赋值的,此时与函数同名的变量赋值会覆盖原有的函数定义。对于一个变量值的确定需要沿着作用域链依照就近原则去确定。注意,未用var定义就直接赋值的变量默认为全局变量。