一.什么是作用域
作用域即定义变量的区域,javascript 是不存在块级作用域的(例如 if 和 for 体现了没有块级作用域),javascript 除了全局作用域之外,只有函数可以创建的作用域。
// 例如:
if (true) {
var name = "kebi";
}
console.log(name); //kebi 此时name是全局作用域,说明没有块级作用域
// ES6的出现 提供了两个定义变量的方式 let/const ,存在块级作用域
// 例如:
if (true) {
const globalName = "kebi";
}
console.log(globalName); //直接报错 is not defined
注意:函数创建的作用域在函数定义时就已经确定了。而不是在函数调用时确定。(这是因为 js 采用的是词法作用域或者静态作用域)(这一点非常重要重要举一个例子)
// 例子一:
var name = "kebi";
function foo() {
console.log(name);
}
function bar() {
var name = "heyushuo";
foo();
}
bar(); //这里打印的是 kebi
//在执行bar函数内部的foo()的时候,应为foo是在全局创建的,所以是在全局作用域,此时全局作用域中name=kebi,所以打印出来的是kebi
// 例子二:
var name = "kebi";
function bar() {
var name = "heyushuo";
function foo() {
console.log(name);
}
foo();
}
bar(); //这里打印的是 heyushuo
//在执行bar函数内部的foo()的时候,应为foo是在bar作用域下创建的,所以是在bar作用域下,此时bar作用域中name=heyushuo,所以打印出来的是heyushuo
通过一张图片更清晰的看一下作用域
如上图,全局代码和 fn、bar 两个函数都会形成一个作用域。而且,作用域有上下级的关系,上下级关系的确定就看函数是在哪个作用域下创建的。例如,fn 作用域下创建了 bar 函数,那么“fn 作用域”就是“bar 作用域”的上级。 作用域最大的用处就是隔离变量,不同作用域下同名变量不会有冲突
二.什么是用域链呢?
通过一个例子来看作用域链;
var name = "kebi";
var age = "36";
function foo() {
var sex = "男";
function bar() {
console.log(name);
}
bar();
}
foo(); //执行这个方法
// bar()函数中打印的是什么呢?
// 1.先在bar作用域里查找变量name,不存在
// 2.接着要到创建这个函数的那个作用域中取值——是“创建”,即foo作用域内,发现还是没有
// 3.最后就是向全局作用域去寻找,发现name是kebi,结束,打印 出 kebi
// 这样一步一步的找,直到找到全局作用域为止,这个路线我们称之为作用域链
参考: