十二.函数作用域与解析顺序
- var
/*
ES5
* var
* function
*
* */
console.log(x);
// 变量提升 -- 解析代码的时候,会先读(当前作用域中)所有的var
var x = 20;
//等价于
var x;
console.log(x);
x = 20;
let x = 20;
console.log(x);
- 基于ES5
/*
* var
* function
*
* */
/*
*
* 1. 定义阶段
* 找到当前作用域中的var定义的变量(只定义变量,不会提前赋值)
* 找到当前作用域中的function定义的函数
*
* 2. 执行阶段
* 从头开始,往下执行代码
*
* */
console.log(x);
var x = 20;
console.log(x);
/*
* 1.定义
* var x;
*
* 2.执行
* console.log(x); //undefined
* x = 20;
* console.log(x); //20
*
* */
- 两个var
16:console.log(x);
17:
// 变量提升 -- 解析代码的时候,会先读(当前作用域中)所有的var
18: var x = 10;
29:
20:
21: console.log(x);
22: var x = 20;
23: console.log(x);
/*
* 1. 定义
* 16: var x;
* 18: var x; (两个var变量冲突,留下一个)
*
* 2. 执行
* 15: console.log(x); // undefined
* 16: x = 10;
* 17: console.log(x); // 10
* 18: x = 20;
* 19: console.log(x); // 20
* */
- function
/*
* 定义(预解析)阶段,function定义的函数会被看成一个整体,里面的代码不会读取
*
* */
20: var x = 20;
21:
22: fn();
23:
24: console.log(x);
25:
26: function fn(){
27: var x = 10;
28: }
/*
* 1. 定义
* 20:var x;
* 26-28: function fn(){函数体}
*
* 2. 执行
* 20:x = 20;
* 22: fn(); ===========产生新作用域=======> 1.定义
* 27:var x;
* 2.执行
* 27: x = 10;(当前作用域有x)
* 24: console.log(x); //20
*
*
* */
- var和function重名
/*
* 定义(预解析)阶段,function定义的函数会被看成一个整体,里面的代码不会读取
*
* */
20:var x = 20;
21:
22:fn();
23:
24:console.log(x);
25:
26:function fn(){
27:var x = 10;
28:
29:}
/*
* 1. 定义
* 20:var x;
* 26-28: function fn(){函数体}
*
* 2. 执行
* 20:x = 20;
* 22: fn(); ===========产生新作用域=======> 1.定义
* 27:var x;
* 2.执行
* 27: x = 10;(当前作用域有x)
* 24: console.log(x); //20
*
*
* */
- function与function重名
/*
* function重名,后面的会覆盖前面的
* */
console.log(fn);
function fn(){
//函数 2
}
function fn(){
//函数 1
}
//打印结果
//function fn(){
// //函数 1
// }
/*
*
*
* 分为 定义 与 执行 阶段
*
* 定义:找 var与function
*
* 执行:从头开始执行代码
*
* */
- 练习
15:var x = 5;
16:a();
17:function a(){
18: alert(x);
19: var x = 10;
20:}
21:alert(x);
/*
*
* 1. 定义
* 15:var x;
* 17-20: function a(){...}
*
* 2.执行
* 15: x = 5;
* 16: a(); ======新的自作用域=======> 1. 定义
* 19:var x;
* 2. 执行
* 18:alert(x); //undefined
* 19: x = 10;(不影响全局)
*
* 21:alert(x); //5
*
*
*
* */
15:a();
16: function a(){
17: alert(x);
18: var x = 10;
19: }
20: alert(x);
/*
* 1. 定义
* 16-19: function a(){...}
*
* 2. 执行
* 15:a(); =====子作用域====> 1.定义
* 18:var x;
* 2. 执行
* 17:alert(x); //undefined
* 18: x = 10;
* 20: alert(x); //报错
*
*
* */
function a(){
alert(1);
}
var a;
alert(a);
//打印函数体 不解释了
15: alert(a);
16: var a = 10;
17: alert(a);
18: function a(){alert(20)}
19: alert(a);
20: var a = 30;
21: alert(a);
22: function a(){alert(40)}
23: alert(a);
/*
* 1. 定义阶段
* 22: function a(){alert(40)}
*
* 2. 执行阶段
* 15: alert(a); // 函数体40
* 16: a = 10;(当前作用域有a,修改自己的a)
* 17: alert(a); // 10
* 19: alert(a); // 10
* 20: a = 30;(当前作用域有a,修改自己的a)
* 21: alert(a); // 30
* 23: alert(a); // 30
*
* */
15: var a = 10;
16: alert(a);
17: a();
18: function a(){
19: alert(20);
20: }
/*
* 1. 定义
* 18-20: function a(){...};
*
* 2. 执行
* 15: a = 10;(自己有a,重新赋值)
* 16: alert(a); //10
* 17: a(); //报错
*
*
* */
15: a();
16: var a = function(){alert(1)};
17: a();
18: function a(){alert(2)};
19: a();
20: var a = function(){alert(3)};
21: a();
/*
* 1. 定义
* 18: function a(){alert(2)};
*
* 2. 执行
* 15: a(); // 2
* 16: a = function(){alert(1)};
* 17: a(); // 1
* 19: a(); // 1
* 20: a = function(){alert(3)};
* 21: a(); // 3
*
* */
15: var a = 10;
16: function fn(){
17: alert(a);
18: var a = 1;
19: alert(a);
20: }
21: fn();
22: alert(a);
/*
* 1. 定义
* 15: var a;
* 16-20: function fn(){...}
*
* 2. 执行
* 15: a = 10;(全局a)
* 21: fn(); =====子作用域=====> 1.定义
* 18: var a;
* 2. 执行
* 17: alert(a); // undefined
* 18: a = 1;(子作用域a改变)
* 19: alert(a); // 1
* 22: alert(a); // 10
*
*
* */
15: var a = 10;
16: function fn(){
17: alert(a);
18: a = 1;
19: alert(a);
20: }
21: fn();
22: alert(a);
/*
* 1. 定义
* 15; var a;
* 16-20: function fn(){...}
* 2. 执行:
* 15: a=10;
* 21: fn(); ====子作用域====> 1. 定义
* 2. 执行
* 17: alert(a); // 10
* 18: a = 1;(子作用域没有a,改变全局的a)
* 19: alert(a); // 1
* 22: alert(a); // 1
*
* */