下面两段代码的执行结果
console.log(person); console.log(fun); var person = 'koa'; console.log(person); function fun() { console.log(person); var person = 'express'; console.log(person); } fun(); console.log(person); // 结果 // undefined // 函数 // koa // undefined // express // koa
console.log('step1'); function first() { console.log('step2'); second(); console.log('step3'); } function second() { console.log('step4'); } first(); console.log('step5'); // 结果 // step1 // step2 // step4 // step3 // step5
js 执行是单线程的,是基于事件循环的,事件循环分为下面几个步骤

主线程的执行过程就是一个 tick,所有的异步结果都是通过任务队列来调度,消息队列中存放着一个个 task,task 分为 macro task 和 micro task,常见的 macro task 分为 setTimeout,MessageChannel,postMessage,setImmediate,常见的 micro task 有 MutationObserver 和 Promise.then
分析 js 代码块语法是否正确,不正确抛出语法错误,停止该 js 代码块的执行,然后加载下一个代码块,语法正确,则进入预编译阶段
js 代码块加载完毕,并且没有语法错误,则进入全局环境
函数调用执行时,进入函数环境,不同函数则函数环境不同
每次进入不同环境,会创建一个对应的上下文,在一段 js 程序中,会创建多个执行上下文,js 引擎会创建一个函数调用栈对这些执行上下文进行处理,栈底永远是全局执行上下文,栈顶永远是当前执行上下文
function bar() {
var name = 'koa';
function foo() {
var age = '22';
}
foo();
}
bar();
在全局环境中,window 对象就是全局执行的上下文变量对象,所有变量和函数都是 window 对象的属性或方法,函数声明提前和变量声明提升时古在创建变量对象中进行的,函数声明优先级高于变量声明
// 创建上下文 function fun(a, b) { var num = 1; function test() { console.log(num); } } fun(2, 3); < !--创建的结果-- > funEC = { //变量对象 VO: { //arguments对象 arguments: { a: undefined, b: undefined, length: 2 }, //test函数 test: < test reference > , //num变量 num: undefined }, //作用域链 scopeChain: [], //this指向 this: window };
作用域链的第一项永远是当前作用域,就是 innerTest,最后一项永远是全局作用域,查找方式是从左到右,直到找到全局作用域,如果再找不到,就报错
// 创建作用域链
var num = 30;
function test() {
var a = 10;
function innerTest() {
var b = 20;
return a + b;
}
innerTest();
}
test();
// 创建结果
innerTestEC = {
//变量对象
VO: {
b: undefined
},
//作用域链
scopeChain: [VO(innerTest), AO(test), AO(global)],
//this指向
this: window
};©2026 Hejian
陕 ICP 备 2025072452 号-1