2018年学习计划(js原理篇)

Javascript是单线程单一并发语言,这意味着它可以一次处理一个任务或一次处理一段代码。它有一个单独的调用堆栈,它与堆之类的其他部分一起构成了Javascript并发模型(在V8内部实现)。我们首先来看看这些术语:

demo

下面是我总结的一张图片:

demo

这里我展开讲,如果需要详细了解请参阅下面参考网址。

下面以一道面试题展开:

1
2
3
4
5
6
7
8
9
10
11
12
13
function Foo() {
getName = function () { alert (1); };
return this;
}
Foo.getName = function () { alert (2);};
Foo.prototype.getName = function () { alert (3);};
var getName = function () { alert (4);};
function getName() { alert (5);}

//请写出以下输出结果:
getName();
Foo().getName();
getName();

执行上下文

代码开始,引擎创建全局执行上下文:

  1. 创建阶段

    • ThisBinding: 这边的this为window对象
    • 词法环境:
      • 环境记录:
        • Foo:
        • getName:
      • 外部环境引用:null
    • 变量环境:
      • 环境记录:
        • getName: undefined
      • 外部环境应用:

正是由于javascript引擎会在执行上下文之前的创建阶段(即变量提升),所以代码实际上是变成如下:

1
2
3
4
5
6
7
8
9
10
function Foo() {
getName = function () { alert (1); };
return this;
}
var getName;//只提升变量声明
function getName() { alert (5);}//提升函数声明,覆盖var的声明

Foo.getName = function () { alert (2);};
Foo.prototype.getName = function () { alert (3);};
getName = function () { alert (4);};//最终的赋值再次覆盖function getName声明

所以第一问的答案输出为4

  1. 执行阶段

调用堆栈

假设当开始执行到Foo().getName()时,开始进入Foo函数,把Foo函数压入调用堆栈顶部。创建Foo局部执行上下文创建阶段:

  • ThisBinding: 由于这边没有对象调用,故为this为window对象
  • 词法环境:
    • 环境记录:
    • 外部环境引用:
  • 变量环境:
    • 环境记录:
      • getName: function(){ alert(4); }
    • 外部环境应用:

return this返回时,Foo函数弹出栈顶,Foo局部执行上下文销毁。

故执行时第二问答案输出1;第三问因为getName已被第二问中修改,故输出1

事件循环

事件循环是指主线程重复从消息队列中取消息、执行的过程。如果遇到同步函数,直接压入调用栈,如果异步代码,则委托给事件队列,然后继续运行代码,当异步处理返回时压入事件队列,主线程在执行完当前循环中的所有代码后,就会到消息队列取出这条消息,并执行它:

demo

参考网址