作用域和作用域链
作用域(Scope)
1. 什么是作用域
是变量、函数、对象访问的范围区域。它的作用是隔离变量防止变量重复导致冲突。
2. 全局作用域和函数作用域
-
作用域分为全局作用域和函数作用域,没有块级作用域(ES之前是没有的)。
-
在代码中任何地方都能访问到的对象拥有全局作用域,以下几种情况拥有全局作用域 1. 如果函数中的变量没有声明就直接赋值,会默认在最外层先声明,所以它有全局作用域
function Fun() {
a = "未声明就赋值"
var b = "声明后赋值"
}
Fun() //先调用才会执行
console.log(a);
console.log(b);
2. 最外层变量、最外层函数有全局作用域
var a="最外层变量";
function Fun() {//最外层函数
var b="内层变量"
function inFun(){
console.log(b);
}
inFun();
}
console.log(a);//最外层变量
Fun()
inFun();
console.log(b);
最外层变量、最外层函数皆能在外层访问到,内部则没有访问到。(inFun() 没有打印b)
3.所有 window 对象的属性拥有全局作用域
一般情况下,window 对象的内置属性都拥有全局作用域,例如 window.name、window.location、window.top 等等。
4.作用域是分层的,内层作用域可以访问外层作用域的变量,反之则不行。
作用域与执行上下文
作用域与执行上下文是两个容易混淆的概念,先要知道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()
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. 什么是作用域链
沿着父级作用域向上查找的机制。