How JavaScript works - 1 (译) js 如何工做

原文连接:an overview of the engine, the runtime, and the call stack

Foreword - 前言

随着js愈来愈流行,团队利用其在更多领域的堆栈,前端,后端,混合app,嵌入设备等。 这篇文章旨在深刻了解js以及它的工做原理。咱们都知道只有了解更多的js基础才能够写出更好的代码和app。javascript

Overview - 概览

几乎全部人都听过V8引擎的概念,也知道js是一个单线程活使用回调队列。 在这篇文章中咱们会详细讲解这些概念和解释js工做原理。知道这些你能够利用js提供的api,写出更好的代码,更流畅的app应用。 若是你刚接触js,这篇博文会帮助你理解js和其余语言相比下的不同凡响。 若是你是一个经验丰富的js开发者,在你天天的工做的时候,在js如何运行上给你一些新的体验。前端

The JavaScript Engine - js引擎

谷歌v8引擎是一个js引擎的典型案例。Chrome和node都是用了v8引擎。下面是一个简单的例图: java

图片

v8引擎由两部分组成:

  • Memory Heap - 内存堆:内存分配
  • Call Stack - 调用栈:调用栈框架代码执行

The Runtime - 运行

浏览器提供的api几乎被全部js开发者使用(eg:'setTimerout')。然而这些api并非v8引擎提供的。 所以他们来自哪里呢? 事实证实现实是有一点复杂的。node

图片

所以,咱们拥有引擎,但实际上还有更多的东西。有浏览器提供的web api,例如 dom,ajax,setTimeout等等。 并且,咱们还有超级流行的 event loop 和 回调队列。web

The Call Stack - 调用栈

js是一个单线程的程序语言,意味着他只有一个调用栈。因此一次只能够作一件事情。 The Call Stack is a data structure which records basically where in the program we are. 若是进入一个函数,咱们把它放入调用栈的顶端。若是我从一个函数返回,咱们把它从调用栈顶端移除,这就是调用栈作的全部事。 看下面demo:ajax

function multiply(x, y) {
        return x * y;
    }
    function printSquare(x) {
        var s = multiply(x, x);
        console.log(s);
    }
    printSquare(5);
复制代码

当引擎开始执行代码,调用栈是空的。而后,接下来的步骤如图: 后端

图片

调用栈中的每个表被称为一个 栈框架(Stack Frame) 当异常被抛出的时候,能够清楚的知道堆栈追踪是如何被构成的。异常发生时堆栈的状态。看一下下面的代码:api

function foo() {
        throw new Error('SessionStack will help you resolve crashes :)');
    }
    function bar() {
        foo();
    }
    function start() {
        bar();
    }
    start();
复制代码

若是这发生在 Chrome 里(假设这段代码实在一个名为 foo.js 的文件中),那么将会生成如下的堆栈追踪 浏览器

图片

堆栈溢出(Blowing the stack) - 当你达到调用栈最大的大小的时候就会发生。并且很容易出现,特别是当你在没有彻底的测试你的代码的状况下使用回调。看下面的简单的代码:session

function(){
        foo();
    }
    foo();
复制代码

当引擎开始解析这段代码的时候,就会开始调用foo函数,这个函数是一段从本身开始没有任何终止条件的递归函数。所以在每一步的执行中,一样的函数被一遍一遍放在调用栈中,这看起来就像这样:

图片
而后在某一时刻,当函数调用栈的数量超过实际调用栈的大小的时候,浏览器会经过抛出异常来采起行动。看起来就像这样:
图片
在单线程中很容易运行代码由于你不用去处理多线程环境下的复杂场景-例如:死锁。 可是在单线程中运行很容易被限制。由于js只有一个单线程,当运行变慢时发生了什么?

Concurrency & the event loop - 并发&事件循环

当你有函数调用堆栈须要花费大量时间处理的时候,发生了什么?例如,你想要在浏览器中使用js去作一些复杂的图片处理的时候。 你可能会问-这怎么是一个问题?问题是当调用栈有函数要执行。浏览器实际上不能够作别的事情--它被锁住了。这意味着浏览器不能够被渲染,也不能够执行其余的代码,它仅仅是卡住了。并且这会对于你想要完美的ui app中形成问题。 并且不单单是这一个问题。一旦你的浏览器在调用栈中开始执行这么多任务,他可能会在很长时间内中止响应。绝大多数浏览器会采起提出一个错误,询问你是否须要关闭web页面。 如今,这难道不是一个很糟糕的用户体验? 因此,咱们在执行大量代码的时候如何不会阻塞ui和浏览器流畅?就决方案就是 异步回调(asynchronous callbacks)。

会在第二章中有更详细的解释:Inside the V8 engine + 5 tips on how to write optimized code

相关文章
相关标签/搜索