一、前言
我们今天来聊聊JavaScript的作用域,聊这个之前先卡看看其他语言包括python在内的,作用域的范围是多少,规则是怎么样的。然后再看看JavaScript的作用域。这样就有对比性。
二、其他语言的作用域
2.1、其他语言
说明:以代码块作为作用域
public void Func(){
if(1==1){
string name = "java";
}
console.writeline(name);// 报错,因为是以代码块作为作用域的,所以报错。
}
Func();
正确的代码:
public void Func(){
if(1==1){
string name = "java";
console.writeline(name); //正确,出了if的代码块就报错
}
}
Func();
2.2、python的作用域
说明:以函数作为作用域
def func():
if 1==1:
name = "alex"
func()
print(name) #报错,因为是以函数作为作用域
正确的代码:
def func():
if 1==1:
name = "alex"
print(name)
func() #正确
三、 JavaScript的作用域特性
3.1、以函数作为作用域(let除外)
function func(){
if(1==1){
var name = 'alex';
}
console.log(name); //作用域是以函数作为作用域
}
func();
3.2、函数的作用域在函数未被调用之前,已经创建
function func(){
if(1==1){
var name = 'alex';
}
console.log(name);
} //浏览器在解释它的过程当中,作用域已经创建了
3.3、函数的作用域存在作用域链,并且也是在被调用之前创建
说明:一个作用域套另外一个作用域,我们称之为作用域链。
示例一:
name = "alex";
function func(){
var name = "sgaogao";
function inner() {
var name = "sbhong";
console.log(name)
}
inner(); //调inner作用域
}
func();
输出:
sbhong
逻辑图:
这张图的意思是:name->先找最近的'sbh'->没有就找'sgg'->再没有就‘alex’->再没有就报错了。
示例二:
说明:作用域链在创建之前被创建
name = "alex";
function func(){
var name = "sgaogao";
function inner() {
//var name = "sbhong";
console.log(name)
}
return inner;
}
var ret = func();
ret(); //跟上面效果是一样的
#输出
sgaogao
注意:就是说在代码在执行之前作用域链就已经生效了,而不是执行的生效,所以在执行之前关系已经建立
示例三:
name = "alex";
function func(){
var name = "sgg";
function inner() {
console.log(name)
}
var name = "tony";
return inner;
}
var ret = func();
ret();
逻辑图:
逻辑说明:先在inner函数内部找 - >func 内部找,这个时候发现name的值变化了,找到最新的name值->再找不到,就找最外面的name。
3.4、函数内部的变量 声明提前
示例一
说明:没有声明变量的情况
function func(){
console.log(name);
}
func();//程序直接会报错
示例二
说明:只声明,没有赋值,JavaScript给你默认赋值一个特殊的值,叫undefined。
function func(){
console.log(name);
var name = "shuaigaogao";
}
func();
//输出
undefined
因为解释器在解释的过程中,先找到function 内部所有的局部变量,然后执行var name;所以在作用域里面声明了,但是没有赋值,所以这个值就默认为undefined。