js 作用域链
局部变量:在函数中通过var声明的变量。
全局变量:在函数外通过var声明的变量。
没有声明就使用的变量,默认为全局变量,不论这个变量在哪被使用。
局部作用域
在函数内部定义的变量,为局部变量,局部变量只能在该局部作用域中访问
function fn1() {
var username = 'jerry';
console.log(username);
}
fn1() // jerry
此时在全局访问username,则会报错
console.log(username); // 报错,username未定义
全局作用域
函数内部和外部都可以访问该变量
var age = 12;
function fn2() {
console.log(age);
}
fn2() // 12
console.log(age); // 12
如果在函数内部没有使用var定义变量,那么 gender = ‘male’;就是个赋值语句,会找到最近的定义的变量进行赋值(注意变量提升),如果都没找到,则为全局变量
function fn3() {
gender = 'male';
console.log(gender);
}
fn3();
如果上面的函数没有调用,那么在外面使用gender会报错,因为在 fn3()
被第一次调用之前, gender
变量是不存在的。fn3()
被调用过之后,gender成为全局变量
多层函数嵌套
如果内层函数没有使用var定义变量,则可以看做是赋值语句,会向上层依次找到该变量的定义语句,并赋值给它,如果向上找都没有没找到,则为全局变量
这里在fn5
函数这个作用域中没有找到num
,则向上查找,找到fn4
作用域中的num
,赋值为100
,则下面的fn4里在fn5调用后的num
是100
var num = 1;
function fn4() {
var num = 10
console.log('fn4里在fn5调用前的num ' + num);
function fn5() {
num = 100
console.log('fn5里的num ' + num);
}
fn5()
console.log('fn4里在fn5调用后的num ' + num);
}
fn4()
console.log('全局的num ' + num);
输出结果:
fn4里在fn5调用前的num 10
fn5里的num 100
fn4里在fn5调用后的num 100
全局的num 1
这里在fn5
函数内部的num = 100
后面加了一个var num = 200
,此时由于存在变量提升,num
定义提升到函数顶部,并初始化为undefined
,然后赋值num = 100
(这里赋值的是fn5
函数内部提升的num
),再赋值num = 200
,因此fn5里的num
输出200,而fn4里在fn5调用后的num
输出10
var num = 1;
function fn4() {
var num = 10
console.log('fn4里在fn5调用前的num ' + num);
function fn5() {
num = 100
var num = 200
console.log('fn5里的num ' + num);
}
fn5()
console.log('fn4里在fn5调用后的num ' + num);
}
fn4()
console.log('全局的num ' + num);
输出结果:
fn4里在fn5调用前的num 10
fn5里的num 200
fn4里在fn5调用后的num 10
全局的num 1
这里在fn5
函数内部的num = 100
后面加了一个let num = 200
,此时由于存在变量提升,num
定义提升到函数顶部,但并不会初始化为undefined
(这是由于let的变量提升和var的变量提升有差异导致的),此时num
提升之后,执行num = 100
,但是由于仅仅提升了变声声明,这个时候并没有初始化为undefined
,因此会报错Uncaught ReferenceError: Cannot access 'num' before initialization
var num = 1;
function fn4() {
var num = 10
console.log('fn4里在fn5调用前的num ' + num);
function fn5() {
num = 100
let num = 200
console.log('fn5里的num ' + num);
}
fn5()
console.log('fn4里在fn5调用后的num ' + num);
}
fn4()
console.log('全局的num ' + num);
输出结果:
fn4里在fn5调用前的num 10
报错: `Uncaught ReferenceError: Cannot access 'num' before initialization`
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 289211569@qq.com