什么是作用域?
任何语言都有 作用域 的概念,简单的说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期。在JavaScript中,变量的作用域有全局作用域、局部作用域和块级作用域(es6)三种。
作用域就是一个独立的地盘,让变量不会外泄、暴露出去。主要作用就是隔离变量,使得不同作用域下的同名变量不会产生冲突。
全局作用域
首先让我们来认识一下什么是全局作用域。
全局作用域可以理解为是所有js代码中最外层那一层环境。因此根据我们对它的了解,我们自然可以知道,全局作用域中的变量可以在任意子作用域中访问、又因为它是所有作用域的祖先作用域。 最终得出结论:在js代码的任何地方都可以访问到全局作用域下的变量。 换个说法:可以在任何作用域下访问到的变量具有全局作用域
让我们看一段代码
<script>
var a = 5;
function func1() {
var b = 10;
console.log("b作用域下访问a:", a); //b作用域下访问a: 5
console.log("b作用域下访问c:", c); //Uncaught ReferenceError: c is not defined
function func2() {
var c = 10;
console.log("c作用域下访问a:", a); //c作用域下访问a: 5
}
func2();
}
func1();
</script>
通过这段代码我们可以得出结论: 变量a和函数func1具备全局作用域,变量b、c和函数func2不具备全局作用域。
- window对象属于全局对象、他下面的属性也具备全局作用域。
通常我们在全局定义的属性和变量都会挂载到window对象下。这样当书写较多代码的时候会造成全局变量的污染。 es6出现let、const使得全局作用域下定义的变量不在挂在到window对象下了。
在一些框架和库中会使用函数的立即调用防止变量定义到全局下
(function(){})()
函数作用域
函数作用域、顾名思义函数内部的作用域,只在函数内部可以访问。
function func (){
function func1(){
}
}
从上段代码 我们可以分成两层、第一层是func内部、第二层使func1内部。我们知道在func1中可以访问func中的变量、但func不可以访问func1内部的变量。
很多初学者会认为是不是一个花括号{}就是一个作用域呢?
其实这是不对的,例如一些语句,例如 if(){} while() do{}while等{}并不能产生作用域。(这里暂时不考虑es6的块级作用域)
块级作用域
块级作用域是通过使用es6新增的let和const声明变量产生的,所声明的变量在指定块的作用域外无法被访问。 块级作用域是使用let、const在{}内部声明变量产生的。
让我们看一段代码 理解一下这段内容。
{
let a = 5;
}
console.log(a) //Uncaught ReferenceError: a is not defined
让我们复习一下let var const的区别
声明变量特点:
- 不可以重复定义
- 不挂在window对象下
- 不存在变量提升
- 存在块级作用域
- 存在暂时性死区
nst声明变量除以上特点外还有 声明的是常量 果是基本数据类型则是不可变、如果是引用数据类型 则内容可变 但地址不可变。(可用Object.freeze(obj) 来冻结它,使它无法改变)
作用域链
首先让我们认识一下作用域链是什么?
⼀般情况下,变量取值到 创建 这个变量 的函数的作⽤域中取值。 但是如果在当前作⽤域中没有查到值,就会向上级作⽤域去查,直到查到全局作⽤ 域,这么⼀个查找过程形成的链条就叫做作⽤域链。
var a = 1;
function func1() {
var b = 2;
function func2() {
console.log(a); // 1
console.log(b); // 2
}
func2();
}
func1();
注意:作用域链取决于它创建时候的环境、并不取决于它执行的环境。 这句话十分重要一定要记住!!! 这一点与执行上下文不同。
让我们看一段代码理解理解
var x = 1;
function func() {
console.log(x);
}
function func1() {
function func2() {
var x = 3;
func();
}
func2();
}
func1(); //1
- func()执行环境中声明了一个局部变量x=3。
- func的定义环境下,声明了一个x=1
- 最终结果输出1
- 由此我们可以确定作用域链是指沿着定义时候的位置从内向外找。
作用域链的精髓在于上方的那句话一定要记住。!!!