js中的作用域、作用域链、域解析
一、作用域:
通俗理解,作用域指的就是变量名能够起作用的区域(也就是说你声明的变量可以在哪些区域进行使用)。javascript中分为两种作用域:全局作用域,局部作用域。
全局作用域是一个非常厉害的东西,我们如果声明在全局作用域的变量,可以在js代码的任何地方都能访问到。局部作用域是一个比较小气的东西,我们在局部作用域声明的变量,不能在全局作用域中使用,也不能在另外一个函数中使用,只能在声明的那个函数里面使用。函数的参数也可以认为是一个局部变量。
全局变量和局部变量的区别:全局变量会一直存在,直到关闭浏览器页面为止。局部变量会在调用函数的时候创建出来,当函数调用完毕的时候又被销毁了。
示例代码如下:
function fn(){
var abc = 123
}
fn()
此时,函数fn内就是一个作用域
二、作用域链:
当我们去访问变量的时候,会现在当前的函数内部查找是否有声明这个变量,如果有就直接使用。如果没有,继续去当前函数的外部查找这个变量,直到找到全局作用域为止。
var num = 998
function fn() {
console.log(num)
}
fn()
console.log(num)
此时,函数fn内输出结果为998,说明函数fn中num通过作用域链找到了全局变量998
三、域解析:
js解释器执行代码的两个步骤:
A.预解析:js解释器会在执行代码之前先将代码 "读" 一遍,找到 var 声明的变量 和function 声明的函数,进行变量提升和函数提升
B.执行代码:按照代码书写的顺序,从上到下,一句一句进行执行
预解析要做的事情:
A.变量名提升:在预解析的时候,会找到var声明的变量,根据变量名在内存中开辟这个名字对应的空间,相当于就是将变量名的声明代码放在了所有代码的前面。
B.函数名提升:在预解析的时候,会找到function声明的函数,只是将函数名称和 函数关联起来了,相当于做完预解析之后,js解释器知道了有一个函数的名字叫什么,不会执行函数。
注意:当我们进行变量初始化的时候,会进行变量名提升,但是不会做赋值操作,赋值操作会在第二个阶段(执行代码)进行操作var num = 123;// 预解析的时候会在内存中开辟一个num的空间。// 代码执行的阶段会将数据123保存到num空间中。
注意:函数名提升:预解析的时候,会解析到fn函数,解析完成之后,js解释器就知道当前作用域中有一个fn函数。执行代码的时候,如果遇到了fn() 调用,就会找到fn函数,进行执行function fn(){ }
如果是一个函数表达式,他是不是进行函数名提升的。foo();// 在赋值函数之前 ,foo只是一个变量,里面没有数据,没有办法进行调用。var foo = function(){ }foo();// 执行完了函数的赋值操作之后,foo就是一个函数了,可以进行正常调用。