一、变量提升与函数提升
- 在JavaScript 中,函数声明(function aa(){})与变量声明(var)经常被 JavaScript 引擎隐式地提升到当前作用域的顶部。
- 函数声明的优先级高于变量,如果变量名跟函数名相同且未赋值,则函数声明会覆盖变量声明
- 声明语句中的赋值部分并不会被提升,只有变量的名称被提升
1. 变量声明提升
通过var声明的变量,在定义语句之前就可以访问到,值为undefined
2. 函数声明提升
通过function声明的函数,在之前就可以直接调用,值为函数定义(对象)
var a = 3;
function fn() {
console.log(a); // undefined
var a = 4;
}
fn();
console.log(b); // undefined
fn2(); // 可调用,函数提升 fn2
fn3(); // 不能,变量提升
var b = 3;
function fn2() {
console.log('fn2');
}
var fn3 = function() {
console.log('fn3');
}
二、执行上下文
1. 代码分类
全局代码
函数(局部)代码
2. 全局执行上下文
1、在执行全局代码前将window确定为全局执行上下文
2、对全局数据进行预处理:
- var定义的全局变量==》undefined,添加为window属性
- function声明的全局函数==》赋值,添加为window的方法
- this==》赋值(window)
3、开始执行全局代码
3. 函数执行上下文
1、在调用函数,准备执行函数体之前,创建对应的函数执行上下文对象
2、对局部数据进行预处理
- 形参变量 => 赋值(实参)=> 添加为执行上下文的属性
- arguments => 赋值(实参列表),添加为执行上下文的属性
- var定义的局部变量 => undefined,添加为执行上下文的属性
- function声明的函数 => 赋值(fun),添加为执行上下文的属性
- this => 赋值(调用函数的对象)
3、开始执行函数体代码
// 全局执行上下文
console.log(a1, window.a1);
a2();
console.log(this);
var a1 = 3;
function a2() {
console.log('a2()');
}
console.log(a1);
// 函数执行上下文
function fn(a1) {
console.log(a1); //2
console.log(a2); // undefined
a3();
console.log(this);
console.log(arguments);
var a2 = 3;
function a3() {
console.log('a3()');
}
}
fn(2, 3);
三、执行上下文栈
在全局代码执行前,js引擎会串讲一个栈来存储管理所有的执行上下文对象;
在全局执行上下文(window)确定后,将其添加到栈中;
在函数执行上下文创建后,将其添加到栈中;
在当前函数执行完后,将栈顶的对象移除;
当所有的代码执行完后,栈中只剩下window
var a = 10;
var bar = function(x) {
var b= 5;
foo(x + 5);
}
var foo = function(y) {
var c = 5;
console.log(a+c+y);
}
bar(10);
bar(10);
调用函数时才会产生执行上下文,一共有5个执行上下文(包含window)
console.log('gb:' + i);
var i =1;
foo(1);
function foo(i) {
if (i === 4) {
return
}
console.log('fb:' + i);
foo(i + 1);
console.log('fe:' + i);
}
console.log('ge:' + i);
依次输出:
gb: undefined
fb: 1
fb:2
fb: 3
fe: 3
fe: 2
fe: 1
gb: 1
整个过程中产生了5个执行上下文: window,foo1,foo2,foo3,foo4
四、测试题
同一个标识符的情况下,变量声明与函数声明都会提升;函数声明会覆盖变量声明,但不会覆盖变量赋值,即:如果声明变量的同时初始化或赋值那么变量优先级高于函数。
测试题1:
function a() { }
var a;
console.log(typeof a); // function
测试题2:
var c = 1;
function c(c) {
console.log(c);
}
c(2); // c is not a function
相当于:
var c;
function c(c) {
console.log(c);
}
c = 1;
c(2); // c is not a function
测试题3:
if (!(b in window)) {
var b = 1;
}
console.log(b); // undefined