作用域:
变量(或者函数)的使用范围。
全局变量:在函数体外使用var声明的变量
全局变量可以在页面的任何位置使用(哪怕是不同的script标签中),如果页面不关闭,占用的空间就不会被释放
局部变量:在函数内部定义的变量,是局部变量,这个函数外不能使用
隐式全局变量:声明变量时,没有使用var关键字就是隐式全局变量,不管这个变量是在函数中还是函数外声明
function f1() {
number=1000;//是隐式全局变量
}
f1();
console.log(number);//1000
全局变量是不能被删除的,隐式全局变量是可以被删除的
var num1=10;
num2=20;
delete num1;//把num1删除了
delete num2;//把num2删除了
console.log(typeof num1);//number,全局变量不能被删除
console.log(num1+10);//20 全局变量不能被删除
console.log(typeof num2);//隐式全局变量被删除了因此是undefined
全局作用域:全局变量的使用范围
局部作用域:局部变量的使用范围
块级作用域:一对大括号就可以看成是一块,在这块区域中定义的变量,只能在这个区域中使用,但是在js中在这个块级作用域中定义的变量,外面也能使用;
说明:js没有块级作用域,只有函数除外
作用域链:
名字查找规则:
优先在当前作用域中寻找,如果找不到,则到外层作用域寻找,直到全局作用域,如果在全局作用域还找不到,则会报错,是报错不是undefined。
undefined:变量只有声明,没有初始化或赋值就使用时
报错:变量或函数没有声明也没有定义就使用时
经验:函数或变量先定义再使用。
var num=10;//如果这段代码中只有这一个地方定义了num变量,则f3中输出10(全局作用域中寻找变量)
function f1() {
var num=20;//如果f3函数中没有定义num变量且f2中也没有定义num变量时,则f3中输出的是20(当前f1函数作用域中寻找变量)
function f2() {
var num=30;//如果f3函数中没有定义num变量时,则f3中输出的是30(当前f2函数作用域中寻找变量)
function f3() {
var num=50;
console.log(num);//输出50,找到当前f3函数里定义的变量(当前f3函数作用域中寻找变量)
}
f3();
}
f2();
}
f1();
上述代码的作用域链情况:
0级作用域中定义并初始化了变量num和函数f1
1级作用域中定义并初始化了变量num和函数f2
2级作用域中定义并初始化了变量num和函数f3
3即作用域中定义并初始化了变量num,并输出变量num的值
名字查找规则:console.log优先搜索3级作用域,如果找到变量,则使用,如果找不到再搜索上级作用域,直到最顶层作用域即0级全局作用域
预解析:提前解析代码
预解析做什么事?
把变量或函数的声明提前了,提前到当前所在的作用域且同一个script标签的最上面
f1();
function f1() {
console.log("函数被调用了");
}
预解析后代码为:
function f1() {}
f1();
function f1() {
console.log("函数被调用了");
}
console.log(num);//undefined,而不是报错
var num=10;
预解析后代码:
var num;
console.log(num);
num=10;
console.log(a);//undefined,而不是报错
var a = 25;
abc();
function abc (){
alert(a);//undefined 会把当前作用域中的a变量声明提前
var a = 10;
}
预解析后代码为:
var a;
console.log(a);
function abc(){}
abc();
function abc(){
var a;
alert(a);
a=10;
}
注意:
预解析中,变量或函数的声明会提前,只会在当前的作用域且同一个script标签内进行
函数中的变量只会提前到函数的作用域中的最前面,不会提前到外层作用域
跨script标签的名字查找规则:
先在当前script标签中找,如果找到则使用,如果找不到,则到当前script标签前面的script标签中找,找到则使用否则报错
假设在多个script标签中函数重名,且在相应的script标签中调用,则会执行各自标签里的函数
<script type="text/javascript">
f1();//函数被调用了2 优先使用当前script标签中的函数
function f1() {
console.log("函数被调用了2");
}
</script>
<script type="text/javascript">
f1();//函数被调用了1 优先使用当前script标签中的函数
function f1() {
console.log("函数被调用了1");
}
</script>
假设函数f1定义在一个script标签中,而这个script标签前、后的一个script标签中调用该方法,则一个报错一个正确执行
<script type="text/javascript">
f1();//报错 当前script标签中没有该函数,则去前面的script标签中找,没有找到则报错
</script>
<script type="text/javascript">
f1();//函数被调用了1 优先使用当前script标签中的函数
function f1() {
console.log("函数被调用了1");
}
</script>
<script type="text/javascript">
f1();//函数被调用了1 当前script标签中没有该函数,则去前面的script标签中找,找到了则执行
</script>
在同一个script标签中,如果函数重名,则执行最后一个函数体里的内容
<script>
f1();//xx
function f1() {
console.log("嘎嘎");
}
function f1() {
console.log("xx");
}
</script>
练习:
function f1() {
var a=9;//局部变量
//隐式全局变量
b=9;
c=9;
console.log(a);//9
console.log(b);//9
console.log(c);//9
}
f1();
console.log(c);// 9
console.log(b);// 9
console.log(a);//报错