Appearance
一、变量提升和函数提升
1.变量提升
- 通过var声明的变量,在定义语句之前就可以访问,值为undefined。
- 通过let声明的变量,在定义语句之前不能访问,会报错,初始化之前不能访问。
2.函数声明提升
- 通过function声明函数,在声明之前可以直接调用。值:函数定义的对象
- 箭头函数声明的函数,在之前访问,报函数未定义。
js
var a = 3
function fn(){
console.log(a)//undefined
var a = 4
}
fn();
const c = 2;
function fn1 (){
console.log('c',c)//初始化之前不能访问c
const c = 4;
}
fn1();
console.log(b)//undefined 变量提升
fn2()//函数提升
var b = 4
function fn2 (){
console.log('f2')
}
fn3();//不能,变量提升
var fn3 = function(){
console.log('fn3')
}
fn4();//fn4未定义
var fn4 = () => {
console.log('fn4')
}二、执行上下文
- 代码分类(位置)
- 全局代码,函数代码(局部代码)
- 全局执行上下文
- 执行全局代码前,将
window确定为全局执行上下文对象 - 对全局数据进行预处理,
var定义的全局变量为undefined,添加为window属性,function声明的全局函数,添加为全局window方法this赋值window - 开始执行全局代码
- 执行全局代码前,将
- 函数执行上下文
- 在调用函数,准备执行函数体之前,创建对应的函数执行上下文对象
- 对局部数据进行处理
- 形参变量=》赋值为(实参)=》添加为执行上下文属性
arguments=》赋值(实参列表),添加为执行上下文属性var定义的局部变量=》undefined,添加为执行上下文属性this=》赋值(调用函数的对象)
js
// 全局执行上下文
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();//a3();
console.log(this)//windows
console.log(arguments)//2,3 //伪数组(2,3)
var a2 = 3;
function a3(a3){
console.log('a3()')
}
}
fn(2,3)三、执行上下文栈
- 在全局代码执行前,js引擎就会创建一个栈来存储关联所有执行
- 在全局代码执行上下文(window)确定后,将其添加到栈中(压栈,在栈最下面)
- 在函数执行上下文创建后,将其添加到栈中(压栈)
- 在函数执行完成后,将栈顶的对象移除(出栈)
- 当所有代码执行完后,栈中只剩下window对象
- 栈和队列:栈:后进先出,队列:先进后出
js
// 执行上下文栈:js执行函数,先有window,然后是执行的函数bar,然后是调用的函数foo。后面的foo先出栈
var a = 10;
var bar = function(x){
var b = 5;
foo(x+b)
}
var foo = function(y){
var c= 5;
console.log(a + c + y)
}
bar(10)js
console.log(1,i) // undefined
var i = 1;
foo(i);
function foo(i){
if(i == 4){
return
}
console.log(2,i) // 1,2,3
foo(i + 1) // 递归调用
console.log(3,i) // 3,2,1
}
console.log(4,i) // 1