先从一个简单的例子出发(先不涉及异步),看看本身是否大体了解浏览器的执行机制:html
console.log(a); var a=1; function foo(a){ console.log(a); var a=2; console.log(a); } foo(a);
undefined 1 2git
若是你的预测结果不同,那你能够看看下面几个常见的误区:github
答:变量提高只提高变量的声明,并不进行赋值。其中变量提高发生在预编译阶段,此时a=undefined,预编译结束后代码以下
//函数声明和变量声明进行提高,且函数声明优先级更高 function foo(a){ console.log(a); var a=2; console.log(a); } var a; console.log(a); a=1; foo(a);
很明显第一个结果为undefined。web
变量声明在顺序上跟在函数声明和形式参数声明以后,同时,若是变量名称跟已经声明的形式参数或函数相同,则变量声明不会干扰已经存在的这类属性。例子中的var a=2,能够拆分为var a;a=2;其中a=2是对参数a进行赋值。
首先你须要理解以下几个概念:数组
JavaScript 中的变量分为基本类型和引用类型。其中,基本类型存在于栈中,引用类型存在于堆中。在js的执行阶段,当执行到a=2这样的赋值语句时,js引擎线程会先判断2是基本类型仍是引用类型,若是它是基本类型,则直接对执行栈中的AO进行赋值a=2(AO会在下面的执行上下文中讲到),如果引用类型,则在堆中存入2,而后用2在堆中的地址对AO进行赋值。
js的执行环境分为三种:浏览器
js每进入一个执行环境就会建立一个执行上下文,并将它放入执行栈中。执行上下文会在下文讲到。安全
js是一门单线程语言,但并不意味着参与js执行过程的线程就只有一个。一个有四个线程参与该过程:
JS引擎线程、事件触发线程、定时器触发线程、HTTP异步请求线程。其中,只有JS引擎线程在执行JS脚本程序,其余三个线程只负责将知足触发条件的处理函数推动事件队列,等待JS引擎线程执行。异步
举一个简单的例子来讲:函数
console.log('script start'); setTimeout(function() { console.log('setTimeout'); }, 0); console.log('script end');
若是还不清楚,能够看看下图:性能
首先,这是一个浏览器环境,其中主线程操做堆和执行栈,而RunTime中存在着许多web API,当主线程读取到setTimeOut等API时,它会交给其余线程来处理(setTimeOut则是定时器触发线程),定时器触发线程会先将setTimeOut中的回调函数存放在event table中,当知足触发条件时(如上面的4ms),就将回调函数推入事件队列(callback queue)中,等待主线程空闲(执行栈中为空),回调函数则被推入执行栈中进行执行。
执行上下文可理解为当前的执行环境,与该运行环境相对应。js引擎每进入一个环境就会建立相应的执行上下文,建立执行上下文的过程当中,主要作了如下三件事件,如图:
其中,变量对象VO(Variable object)用于存放声明后的变量、函数和形参。咱们举一个例子来讲:
var a = 10; function test(x) { var b = 20; }; test(30);
对应的变量对象是:
// 全局上下文的变量对象 VO(global) = { a: undefined, test: <reference to function> //<reference to function>是test函数位于堆中的地址 }; // test函数上下文的变量对象 VO(test) = { arguments: { x:undefined, length:1 }, b: undefined };
当预编译结束,js进入解释执行阶段时,VO就会转化为AO(Active object),也就是活动对象。AO中变量和参数的值再也不是undefined,它们的值会随着js的逐步执行而发生变化。
做用域链用于代表上下文的执行顺序。上例中的做用域链为:
scopeChain: [VO(test), AO(global)],
this指向当前做用域。这里不作过多分析。
js的执行分为三个阶段:
一样,咱们举一个例子进行分析:
var a = 1; function bar() { var b = 2; function foo() { var c = 3; } foo(); console.log(b) } function coo() { alert("hello") } bar() coo()
咱们解释一下以上过程:
至此,你已基本理解了js的执行机制。