一、概要
-
作用域指的是您有权访问的变量集合。 引用自《w3school》
执行环境(简称环境),是js的一个重要的概念。定义了变量或数据有权访问的其他数据。决定了他们各自的行为。- 每个
执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都存储在这个对象中,我们的代码无法编辑这个对象,但是解析器处理数据时会在后台使用它。 - 在web浏览器中,全局的执行环境被认为是
window对象。 每个函数都有自己的执行环境,当执行流进入一个函数时,函数的环境就会被推进一个环境栈中,当函数执行之后,栈将其环境弹出,把控制权返回之前的执行环境。 概念性的内容是不直观且感受不到的,接下来我们伴着代码和概念一起梳理。
<示例1>
function func() {
var a = "我是变量";
}
func();
console.log(a);//Uncaught ReferenceError: a is not defined at <anonymous>:5:13
根据上面的示例,应该有一个基本的概念,作用域定义了变量的作用范围。说白一点就是一个变量在什么“范围”才起作用。如上例,超出了这个“范围”,就不起作用了。
二、作用域类型
- JS作用域类型分为
全局作用域和局部作用域。观看下面示例 <示例2>var galbalA = '我是全局变量'; function func() { var a = "我是局部变量"; console.log(galbalA);// 我是全局变量 } func(); console.log(galbalA); // 我是全局变量 console.log(a);//Uncaught ReferenceError: a is not defined at <anonymous>:5:13示例2为最外层定义的函数和变量,他们的作用域就是全局的,所以在func中执行对galbalA变量的引用程序是正常执行的。但是变量a就是局部作用域的,他只能在func内部起作用。所以在超出了a的作用域使用它就会报错。 - 全局作用域
-
全局作用域不难理解,就是拥有全局作用域的变量(如上述<示例2>中的galbalA),在代码任何位置都可以被访问。那么全局变量所属的作用域就称之为全局作用域,。
-
什么情况下会产生
全局变量?
- 所有 window 对象的属性和方法
查看window属性和方法,正常的环境下,无论任何位置window对象的属性方法是可以被全局访问的
- 最外层函数及最外层函数外定义的变量
参考<示例2>的galbalA和函数func
- 创建了变量字段但未声明的变量
<示例3>
// console.log(b); function func() { var a = "我是局部变量"; b="未声明变量" } func(); console.log(b); // 未声明变量
-
- 局部作用域
- 函数作用域:在 JavaScript 函数中声明的变量,会成为函数的局部变量。
2. 块级作用域
- ES6之前是没有块级作用域的。
- ES6出现后,对于块级作用域的使用,let、const,如下<示例4> <示例4>
{
var test1 = '1'
}
console.log(test1) // 1
{
let test2 = '2';
console.log('块内部console:',test2) //块内部console: 2
}
console.log('块外部console:',test2) //Uncaught ReferenceError: test2 is not defined
at <anonymous>:9:27
- 变量提升
JavaScript 中,函数及变量的声明都将被提升到函数的最顶部 <示例5>
console.log(name1) //undefined
var name1 = 'my name'
console.log(name1) //my name
上例子中,在未声明变量的上面执行打印不是报错而是打印undefined,说明变量出现了提升。隐式的完整代码应该是:
<示例6>
// 在顶层提升变量
var name
console.log(name1) //undefined
// 这这里定义变量值
name1 = 'my name'
console.log(name1) //my name
四、作用域链
- 自由变量 在当前作用域使用但没有定义,继续向父级作用查找可以找到该变量声明定义的变量。
- 作用域链
上面讲了自由变量及其查找方式,那么这种向父级作用域一级一级的查找,直到全局作用域的作用域关系,形成了作用域链
var a = 1; //--- 父父级作用域
function func1() { //--- 父级作用域
var b = 2;
function func2() {//--- 当前作用域
var c = 33;
console.log(a); // 父父级-自由变量
console.log(b); // 父级-自由变量
console.log(c); // 本级作用域的变量
}
}
五、结语
- 时间关系整理这么多,后续会持续更新,有问题欢迎各位大佬能帮忙指正。