JavaScript整个执行过程,分为两个阶段,代码编译阶段和代码执行阶段node
编译阶段由编译器执行,将代码翻译成可执行代码,这个阶段肯定做用域规则。数组
变量的预编译只做声明,不做初始化,初始化在执行时浏览器
function语句定义的函数,不只声明了函数名,并且函数体也进行了处理bash
2、执行阶段函数
执行阶段由引擎完成,主要任务是执行可执行代码,执行上下文在这个阶段建立。执行上下文也分为建立阶段和执行阶段。ui
一、执行上下文this
执行上下文能够理解为当前代码的执行环境,它会造成一个做用域。spa
二、三种类型翻译
a、全局执行上下文:浏览器的全局对象是window对象,this指向这个全局对象code
b、函数执行上下文:存在无数个,只有在函数被调用的时候才会被建立,每次调用函数都会建立一个新的执行上下文,函数上下文的变量对象初始化只包括 Arguments 对象。
c、Eval函数执行上下文:指运行在eval函数的代码,不多用并且不建议使用。。
建立阶段:
肯定this的值,也被成为 This Binding;
This Binding
a、全局执行上下文中,this 指向全局对象,在浏览器中this 指向window对象,在nodejs中指向这个文件的module 对象。
b、函数执行上下文中,this的值取决于函数的调用方式。具体有:默认绑定、隐式绑定、显式绑定、new绑定、箭头函数。
例一:变量提高
foo(); // 报错
var foo = function () {
console.log('foo1');
}
foo(); // foo1,foo从新赋值
var foo = function () {
console.log('foo2');
}
foo(); // foo2,foo从新赋值
复制代码
例二:函数提高
foo(); // foo2
function foo() {
console.log('foo1');
}
foo(); // foo2
function foo() {
console.log('foo2');
}
foo(); // foo2
复制代码
例三:声明优先级,函数 > 变量
foo(); // foo2
var foo = function() {
console.log('foo1');
}
foo(); // foo1,foo从新赋值
function foo() {
console.log('foo2');
}
foo(); // foo1
复制代码
须要注意的是同一做用域下存在多个同名函数声明,后面的会替换前面的函数声明。
3、执行上下文栈
由于JS引擎建立了不少的执行上下文,因此JS引擎建立了执行上下文栈(Execution context stack,ECS)来管理执行上下文。
当 JavaScript 初始化的时候会向执行上下文栈压入一个全局执行上下文,咱们用 globalContext 表示它,而且只有当整个应用程序结束的时候,执行栈才会被清空,因此程序结束以前, 执行栈最底部永远有个 globalContext。
ECStack = [ // 使用数组模拟栈
globalContext
];复制代码
当执行一个函数的时候,就会建立一个执行上下文,而且压入执行上下文栈,当函数执行完毕的时候,就会将函数的执行上下文从栈中弹出。
var scope = "global scope";
function checkscope(){
var scope = "local scope1";
function f(){
console.log(scope);
}
return f(); //执行
}
checkscope();
var scope = "global scope";
function checkscope(){
var scope = "local scope22";
function f(){
console.log(scope);
}
return f; //返回function
}
checkscope()();复制代码
第一段代码:
ECStack.push(<checkscope> functionContext);//执行checkscope
ECStack.push(<f> functionContext);//执行f
ECStack.pop();//弹出f
ECStack.pop();//弹窗checkscope复制代码
第二段代码:
ECStack.push(<checkscope> functionContext);//执行checkscope
ECStack.pop();//返回function
ECStack.push(<f> functionContext);//执行f
ECStack.pop();//返回f复制代码