深入理解JavaScript作用域和作用域链

169 阅读2分钟

作用域和作用域链

作用域(Scope)

1. 什么是作用域

是变量、函数、对象访问的范围区域。它的作用是隔离变量防止变量重复导致冲突。

2. 全局作用域和函数作用域

  • 作用域分为全局作用域和函数作用域,没有块级作用域(ES之前是没有的)。

  • 在代码中任何地方都能访问到的对象拥有全局作用域,以下几种情况拥有全局作用域 1. 如果函数中的变量没有声明就直接赋值,会默认在最外层先声明,所以它有全局作用域

		function Fun() {
			a = "未声明就赋值"
			var b = "声明后赋值"
		}
		Fun() //先调用才会执行
		console.log(a);
		console.log(b);
	

1.jpg

2. 最外层变量、最外层函数有全局作用域

                var a="最外层变量";
		function Fun() {//最外层函数
			var b="内层变量"
			function inFun(){
				console.log(b);
			}
			inFun();
		}
		console.log(a);//最外层变量
		Fun()  
		inFun();
		console.log(b);

1.jpg

最外层变量、最外层函数皆能在外层访问到,内部则没有访问到。(inFun() 没有打印b)

3.所有 window 对象的属性拥有全局作用域

一般情况下,window 对象的内置属性都拥有全局作用域,例如 window.name、window.location、window.top 等等。

4.作用域是分层的,内层作用域可以访问外层作用域的变量,反之则不行。

1.jpg

作用域与执行上下文

作用域与执行上下文是两个容易混淆的概念,先要知道javascript是解释型语言,分为解释执行两个阶段。这两个阶段做的事情是不同的。

解释阶段:

词法分析

语法分析

作用域规则确定

执行阶段:

执行上下文

执行函数

垃圾回收

作用域在解释阶段便会确定,而执行上下文是在函数执行之前确定的,执行上下文最明显的区别是this的指向是执行时确定的,而作用域的变量的访问是编写代码结构时确定的。

作用域与执行上下文最大的区别: 执行上下文 是运行时确定的,随时会改变。作用域是定义时确定的,并且不会改变。

作用域链

1.什么是自由变量

当前作用域中没有定义,调用时需要通过其创建函数的作用域链沿父级向上查找的变量。

var a = 100
function F1() {
    var b = 200
    function F2() {
        var c = 300
        console.log(a) // 自由变量,顺作用域链向父作用域找
        console.log(b) // 自由变量,顺作用域链向父作用域找
        console.log(c) // 本作用域的变量
    }
    F2()
}
F1()

1.jpg

var a = 10
function fn() {
  var b = 20
  function bar() {
    console.log(a + b) //30
  }
  return bar
}
var x = fn(),
  b = 200
x() //bar()最后的结果是 30

2. 什么是作用域链

沿着父级作用域向上查找的机制。