一、什么是作用域
变量访问的有效范围
1、作用域外,无法引用作用域内的变量
2、离开作用域后,作用域的变量的内存空间会被清除,比如执行完函数或者关闭浏览器。
二、全局作用域
1、在浏览器环境中声明变量,该变量会默认成为全局 windows 对象的属性。
2、在函数中,如果不加 var声明一个变量,那么这个变量会默认被声明为全局变量,如果是严格模式则会报错。
// 1
foo = 'foo'
console.log(window.foo); // foo
//2
function fc() {
name = 'aaa'
}
fc()
console.log(window.name); // aaa
//3
var a = 'ccc'
console.log(window.a); // ccc
全局变量可以在任何地方访问到,但是容易造成命名污染。
三、函数作用域
JS 是函数作用域,在函数中定义一个局部变量,那么该变量只可以在该函数作用域中被访问。
function doSomething() {
var thing = "吃早餐";
}
console.log(thing); // 报错
在外层函数中,嵌套一个内层函数,那么这个内层函数可以向上访问到外部作用域的变量。内层函数可以访问到外层函数的变量,如果外层函数把内层函数返回,那外层函数的变量得以保存。
function outter() {
var thing = "吃晚餐";
function inner() {
console.log(thing);
}
return inner;
}
var foo = outter();
foo(); // 吃晚餐
四、块级作用域
JS 在 ES6 之前只有函数作用域,没有块级作用域的概念。
ES 6 中通过 let 和 const关键字 引用了块级作用域的概念,所谓块级作用域,就是以 {}包裹的区域。
var a = [];
for (let i = 0; i < 10; i++) {
a[i] = function () {
console.log(i);
};
}
a[6](); // 6;
let 和 const 会声明一个块级作用域的变量及常量,不易发生变量命名污染的问题,能规避冲突。
五、词法作用域(静态作用域)
无论函数在哪里调用,词法作用域都只由函数被声明时所处的位置决定。
//1
var a = 123;
function func1() {
console.log(a);
}
function func2() {
var a = 456;
func1();
}
func2(); // 123
// 2
var b = 123;
function funcb() {
var b = 456;
function funca() {
console.log(b);
}
funca();
}
funcb(); // 456
六、作用域链
函数作用域的嵌套就组成了所谓的函数作用域链。当在自身作用域内找不到该变量的时候,会沿着作用域链逐步向上查找,若在全局作用域内部仍找不到该变量,则会抛出异常。
网友评论