以下知识结构来源于《javascript权威指南》,继续学习中。
一个变量的作用域是程序源代码中定义这个变量的区域。
也就是说你这个变量是在哪里写的,那么这个变量就是哪里的的。和我们人出生一样。我们生在哪里,户口就是哪里的,我们就是哪里人,不能随便乱来。
全局变量拥有全局作用域。在JS代码任何地方都有定义。然而函数内的在函数体内有定义而已。他们是局部变量,作用域局部,函数参数也是局部变量,只在函数体内有定义。有定义的意思就是可以找到并且访问。
在函数体内局部变量 优先级 高于全局,也就是说函数体内有同名的,会直接访问函数体内的而不是全局作用域中的变量。
函数体内可以定义函数,这样产生了作用域嵌套的情况。
花括号括起来的代码都具有各自的作用域,而且声明的变量在这个代码块以外的地方不可见。这就做块级作用域。
JS并没有大家别怕。
但是有函数作用域。变量在这个函数体内以及嵌套的函数体内都是有定义的。
函数作用域就是函数体内声明的所有变量在函数体内始终可见。有些变量在声明之前就可以使用了,这个特性叫做声明提前。
就是说JS函数里声明的所有变量都被提前到了函数体的顶部。
当声明了一个全局变量时,实际上是定义了全局对象的一个属性。当使用了var 声明一个变量时,创建的这个属性是不可配置的。
也就是说无法通过delete运算符删除。
当没有使用严格模式,并给一个未声明的变量赋值,JS自动创建了一个全局变量,这种方式创建的变量是全局对象的正常的可配置属性,可以delete.
全局变量是全局对象的属性。我们可以想象到,局部变量当作跟函数调用的相关的某个对象的属性。ES3把它叫做调用对象。ES5叫做声明上下文对象。
可以用this引用全局对象,但是没有方法引用这种声明上下文对象。这是一种不可见的内部实现。这种局部变量对象存在的观念很重要。
作用域链的概念由此牵引出来。JS是基于词法作用域的语言:通过阅读包含变量定义在内的数行源码就能知道变量的作用域。
全局变量在程序任何地方有定义。局部变量只在声明他的函数体内以及嵌套的函数内始终有定义。
如果把局部变量看作是某种自定义实现的对象的属性的话,那么可以这样解读变量作用域。每一段JS代码都有一个与之关联的作用域链,这个作用域链是一个对象列表或者链表,这组对象定义了这段代码作用域中的变量,当JS需要查找X,过程叫做变量解析。他会从链中第一个对象开始查找,如果在这个这个对象有x 则使用,如果第一个不存在就查找链上的下一个对象。依次类推,如果作用域链上不存在x 则抛出引用错误。
在JS最顶层代码中,作用域链由一个全局对象组成,在不包含嵌套的函数体内,作用域链上有两个对象,第一个是定义了函数参数和局部变量的对象,第二个是全局对象。
当定义了一个函数时,实际上是保存了一个作用域链,当调用这个函数时,他创建了一个新的对象来存储他的局部变量,并把这个对象添加到这个保存了的作用域链上,同时创建了一个新的更长的表示函数调用作用域的链。
下面是我自己梳理的一些概念图,不对之处请大力指出。