作用域与作用域链学习笔记
作用域指程序中定义变量的区域,它决定了当前执行代码对变量的访问权限。 作用域就是一个独立的地盘,让变量不会外泄、暴露出去,也就是说 作用域最大的用处就是隔离变量,不同作用域下同名变量不会有冲突。
全局作用域和函数作用域
全局作用域的情况
-
最外层函数和在最外层函数外面定义的变量拥有全局作用域。 所有未定义直接赋值的变量拥有全局作用域。 所有window对象的属性拥有全局作用域
全局作用域有个弊端:如果我们写了很多行 JS 代码,变量定义都没有用函数包括,那么它们就全部都在全局作用域中。这样就会 污染全局命名空间, 容易引起命名冲突。
// 不带var的情况,相当于给window对象设置一个属性 // 1 console.log(a, b) var a =12, b =林一一 function foo(){ // 2 console.log(a, b) // 3 var a = b =13 console.log(a, b) } foo() console.log(a, b) /* 输出: undefined undefined undefined "林一一" 13 13 12 13 */
函数作用域
是指声明在函数内部的变量,和全局作用域相反,局部作用域一般只在固定的代码片段内可访问到,最常见的例如函数内部。
值得注意的是:块语句(大括号“{}”中间的语句),如 if 和 switch 条件语句或 for 和 while 循环语句,不像函数,它们不会创建一个新的作用域。
块级作用域
块级作用域可通过新增命令let和const声明,所声明的变量在指定块的作用域外无法被访问。在大括号中使用let和const声明的变量存在于块级作用域中。在大括号之外不能访问这些变量。
-
声明变量不会提升到代码块顶部 禁止重复声明 循环中的绑定块作用域的妙用
for (let i = 0; i < 10; i++) { // ... } console.log(i); // ReferenceError: i is not defined
作用域链
当前作用域没有定义的变量,这称为 自由变量 。
Javascript的作用域也可以嵌套,Javascript引擎会层层遍历作用域来寻找用到的变量,这种一层一层的关系就是 作用域链。
取自由变量x的值时,要到哪个作用域中取?——要到创建fn函数的那个作用域中取,无论**fn**函数将在哪里调用。
var x = 10 function fn() { console.log(x) } function show(f) { var x = 20 (function() { f() //10,而不是20 })() } show(fn)
var a = 10 function fn() { var b = 20 function bar() { console.log(a + b) //30 } return bar } var x = fn(), b = 200 x() //bar() //fn()返回的是bar函数,赋值给x。执行x(),即执行bar函数代码。取b的值时,直接在fn作用域取出。取a的值时,试图在fn作用域取,但是取不到,只能转向创建fn的那个作用域中去查找,结果找到了,所以最后的结果是30