文章目录
1. JavaScript作用域
1.1 变量的作用域
1.1.1 全局变量
- 在全局作用域下声明的变量都是全局变量
- 全局变量在代码任何位置都可以使用
- 特殊情况:在函数内未声明但赋值的变量也是全局变量(不推荐)
function f(){
num = 10;
}
console.log(num); // => 10
1.1.2 局部变量
- 在函数内部定义的变量
1.1.3 局部变量与全局变量的区别
- 全局变量:在任何一个地方都可以使用,浏览器关闭时才销毁
- 局部变量:在函数内部使用,其代码执行的时候被初始化,代码块运行结束即被销毁
1.2 作用域链
- 根据在内部函数可以访问外部函数变量这种机制,用链式查找决定哪些数据能被内部函数访问,就称为作用域链
var num = 10;
function f(){
var num = 20;
function f(){
console.log(num);
}
}
f(); // => 20
2. 预解析
- js解析器在运行js代码的时候分为两步:预解析和代码执行
- 预解析: js引擎会把js里面所有的 var 还有 function提升到当前作用域的最前面
- 代码执行:按照代码顺序从上往下执行
- 预解析分为变量预解析(变量提升)与函数预解析(函数提升)
2.1 变量预解析
- 变量预解析就是把所有变量声明提升到当前作用域最前面,不提升赋值操作
console.log(num); // => undefined
var num = 10;
f2(); // => err: Uncaught TypeError: f2 is not a function
var f2 = function () {
console.log("I am f2");
}
思考上述两段代码为什么打印结果在意料之外?
在预解析后,代码其实是长这样子的:
var num;
console.log(num);
num = 10;
var f2;
f2();
f2 = function () {
console.log("I am f2");
}
2.2 函数预解析
- 函数提升:把所有函数声明提升到当前作用域的最前面,不调用函数
f1(); // => I am f1
function f1() {
console.log("I am f1");
}
思考:为什么这次能够运行 ?
同理,预解析后代码长这样:
function f1() {
console.log("I am f1");
}
f1();
2.3 预解析思考题
- 思考下列代码会输出什么并写出预解析后的下列代码
2.3.1
var n = 10;
f(); // => undefined
function f() {
console.log(n);
var n = 20;
}
预解析后:
var n;
function f(){
var n;
console.log(n)
n = 20;
}
n = 20;
f();
2.3.2
f(); // => 9 9 9
console.log(c); // => 9
console.log(b); // => 9
console.log(a); // => err: a is not defined
function f(){
var a = b = c = 9;
console.log(a);
console.log(b);
console.log(c);
}
预解析后:
- 注意观察b c赋值,已成为全局变量
function f(){
var a;
a = 9;
b = 9;
c = 9;
console.log(a);
console.log(b);
console.log(c);
}
f();
console.log(c);
console.log(b);
console.log(a);
;
b = 9;
c = 9;
console.log(a);
console.log(b);
console.log©;
}
f();
console.log©;
console.log(b);
console.log(a);