1. 作用域
作用域,顾名思义,指一个变量的作用范围。在js中有两种作用域。
-
全局作用域
-
全局作用域作用于整个script标签,在页面打开时创建,在页面关闭时销毁
-
两种情况可以产生全局作用域
- 全局声明(直接编写在script标签内的代码)
- 在函数内部,没有声明就直接进行赋值
-
全局作用域中有一个全局对象window,代表一个浏览器的窗口,由浏览器创建,我们可以直接使用。
-
全局作用域中创建的变量都会作为window对象的属性保存:
-
var a = 10;
/*
* a 变量创建出来后,会默认保存在window对象的属性中,所以说 a 也是window的属性名
* 在打印的时候,也可以直接使用window调用。
*
* console.log(window.a);
* 打印结果:
* 10
*
* 使用window来直接调用 a 变量,所打印的结果是 10 ,这个 10 就是在创建 a 变量时初始化设置的参数值
*
*/
console.log(window.a);
全局作用域中创建的函数都会作为window对象的方法保存
function fun(){
console.log('我是fun函数');
}
/*
* fun()函数创建出来后,也会默认保存在window对象的属性方法中,所以说 fun() 函数也是window的属性方法,
* 在打印的时候,也可以直接使用window调用。
*
* window.fun();
* 打印结果:
* 我是fun函数
*
* 使用window来直接调用fun()函数,所打印的结果是可以被调用,‘我是fun函数’是fun()函数代码块中的console.log()
*/
window.fun();
-
局部作用域
只在函数内部起作用,节约资源
-
作用域链
想要得到某一变量,但是在当前的作用域中没有定义,这种变量称为自由变量。
自由变量的值如何得到 —— 向上一层层找,按照就近原则,直到找到全局作用域,这种层级关系就是作用域链。
2. 预解析
在当前作用域中,JavaScript代码执行之前,浏览器首先会默认的把所有带var和function声明的变量进行提前的声明或者定义。
变量提升
所有变量声明提升到当前作用域的最前面,赋值不提升
console.log(num);
var num = 10;
//显示结果应为undefined
相当于执行了以下代码:(只提升声明,不提升赋值)
var num;
console.log(num);
num = 10;
函数提升
将function声明的变量进行提前的声明或者定义。
看一个例子:
以下函数先调用fun()再声明函数,会报错
fun();
var fun = function(){
condole.log(22);
}
//报错
相当于执行了以下代码:(只提升声明,不提升赋值)
var fun;
fun();
fun = function(){
condole.log(22);
}
但如果这样写,函数就能正确调用,因为fun()的声明会被提前
fun();
function fun(){
condole.log(11);
}
//可以正确调用函数
提升后:
function fun(){
condole.log(11);
}
fun();
//可以正确调用函数
让我们看更多的例子:
例1.
var num = 10;
fun();
function fun(){
console.log(num);
var num = 20;
}
相当于:
var num;
function fun(){
var num; //函数内部变量也要提升
console.log(num); //输出时num还没有被赋值,所以结果为undefined
num = 20;
}
num = 10;
fun();
}
例2.
var num = 10;
function fn(){
console.log(num);
var num = 20;
console.log(num);
}
fn();
相当于:
var num;
function fn(){
var num;
console.log(num); //第一次输出undefined
num = 20;
console.log(num); //第二次输出20
}
num = 10;
fn();
**例3.(难)
f1();
console.log(c);
console.log(b);
console.log(a);
function f1(){
var a = b = c = 9; //var a = 9; b = 9; c = 9;
//b和c没有声明直接赋值,属于全局变量
console.log(a);
console.log(b);
console.log(c);
}
这里的
var a = b = c = 9;
相当于:
var a = 9; b = 9; c = 9;
特别注意:此处b和c没有声明,直接进行赋值,所以属于全局变量。
如果想要集体声明,应该写成:
var a = 9, b = 9, c = 9;
提升后的代码为:
//function 提升到最前面
function f1(){
//var a = 9; b = 9; c = 9;提升后:
var a;
a = b = c = 9;
console.log(a);
console.log(b);
console.log(c);
}
f1();
console.log(c);
console.log(b); //b和c是全局变量,所以可以输出
console.log(a); //a是局部变量,此处undefined
//结果为9,9,9,9,9,undefined