这几天看犀牛书的一点心得和总结,做个笔记吧,主要是概念层面的,JS高手大可忽略。
变量的作用域
变量的作用域其实很简单:在函数内定义的局部变量只在本函数内有效,在所有函数体外定义的变量在JS代码的全局有限,叫全局变量。有一个特殊情况,如果有全局变量和局部变量重名了,局部变量优先级高于全局变量,为什么会这样?后面再加以解释。
变量与对象属性
在学习Javascript的时候,会发现变量的使用与对象属性非常类似,比如赋值,已经在表达式中的使用方式,你甚至就可以把JS里面的每一个变量都理解为对象的属性。
var a = 10;
var sampleObj = {value1:10; value2:20}
sum = a + sampleObj.value1 //计算结果是20因为在Javascript解释器运行的时候,它总是会首先创建一个全局对象,你定义的全局变量其实就是这个全局对象的属性。
在函数中定义的局部变量同样是对象的属性,这个对象比较特殊,它叫调用对象。在Javascript解释器每次执行一个函数的时候,都会为这个函数创建一个执行环境,而这个执行环境会创建一个调用对象。不同的函数的执行环境是彼此独立的,而在所有函数之外的代码执行环境叫做全局执行环境。
现在再回头总结一下,JS解释器解释代码前创建了一个全局对象,在代码执行到函数之前,代码在全局执行环境中;当解释器执行函数时,进入函数独立的执行环境,并创建调用对象,在函数中定义变量相当于定义了这个调用对象的一个属性。现在能理解了吧?
变量的作用域链
本文开头关于局部变量和全局变量优先级的问题,很快就能解释了,不过首先要知道作用域链的概念。“每个Javascript执行环境都有一个与它关联在一起的作用域链。”这是犀牛书上的表述,把它翻译成大白话就是:作用域的优先级顺序。
作用域链作用:
当Javascritp需要查询变量x的值时,它首先开始查询作用域链的第一个对象,如果该对象有名为x的属性,就采用这个值,如果没有,就查询作用域链上的第二个对象,以此类推。
作用域链的顺序:
根据执行环境来定,假设当前执行环境在两层嵌套的局部函数中,当前函数的调用对象处于作用域链第一位,外层函数调用对象在作用域链第二位,然后再外面的全局对象在第三位。
因此,在函数内部定义的局部变量肯定有比同名全局变量更高的优先级。