《 how JavaScript works: an overview of engine, the run time, and the call stack》读后感(翻译)

简介: 学习JavaScript笔记

As JavaScript is getting more and more popular, teams are leveraging its support on many levels in their stack - front-end, back-end, hybrid apps, embedded devices and much more.

This post is meant to be the first in a series aimed at digging deeper into JavaScript and how it actually works: we thought that by knowing the building blocks of JavaScript and how they come to play together you’ll be able to write better code and apps. We’ll also share some rules of thumb we use when building SessionStack, a lightweight JavaScript application that has to be robust and highly-performant in order to stay competitive.

As shown in the GitHut stats, JavaScript is at the top in terms of Active Repositories and Total Pushes in GitHub. It doesn’t lag behind much in the other categories either.

If projects are getting so much dependent on JavaScript, this means that developers have to be utilizing everything that the language and the ecosystem provide with deeper and deeper understanding of the internals, in order to build amazing software.

As it turns out, there are a lot of developers that are using JavaScript on a daily basis but don’t have the knowledge of what happens under the hood.

开篇大致意思为:JavaScript现在变得越来越流行,社区其实也很活跃,但是很多使用这门语言的人还是不知道它的运行机制,作者认为了解JavaScript程序的工作机制能让使用者写出更好的代码。we thought that by knowing the building blocks of JavaScript and how they come to play together you’ll be able to write better code and apps

Overview

Almost everyone has already heard of the V8 Engine as a concept, and most people know that JavaScript is single-threaded or that it is using a callback queue.

In this post, we’ll go through all these concepts in detail and explain how JavaScript actually runs. By knowing these details, you’ll be able to write better, non-blocking apps that are properly leveraging the provided APIs.

If you’re relatively new to JavaScript, this blog post will help you understand why JavaScript is so “weird” compared to other languages.

And if you’re an experienced JavaScript developer, hopefully, it will give you some fresh insights on how the JavaScript Runtime you’re using every day actually works.

概述

主要说这篇文章说的是JavaScript运行细节,新手可以通过这篇文章了解到 JavaScript与其他语言相比为什么如此奇怪,老手可以获得一些新鲜的观点,了解每天都在使用的语言的内部细节。

The JavaScript Engine

A popular example of a JavaScript Engine is Google’s V8 engine. The V8 engine is used inside Chrome and Node.js for example. Here is a very simplified view of what it looks like:

img

ps:这图真的太经典了

The Engine consists of two main components:
* Memory Heap — this is where the memory allocation happens
* Call Stack — this is where your stack frames are as your code executes

这一节就说JavaScript的V8引擎主要分两部分,1是内存堆,分配内存的地方,2是访问站,程序执行的地方。

The Runtime

There are APIs in the browser that have been used by almost any JavaScript developer out there (e.g. “setTimeout”). Those APIs, however, are not provided by the Engine.

So, where are they coming from?

It turns out that the reality is a bit more complicated.

img

ps: 齐活了

So, we have the Engine but there is actually a lot more. We have those things called Web APIs which are provided by browsers, like the DOM, AJAX, setTimeout and much more.

And then, we have the so popular event loop and the callback queue.

这一节是说开发者使用的大多数浏览器API并不是JavaScript引擎提供的,JavaScript的运行时包括了引擎,还有Web API,比如图中的DOM,AJAX,定时器等,而且还有事件循环和回调队列。

The Call Stack

JavaScript is a single-threaded programming language, which means it has a single Call Stack. Therefore it can do one thing at a time.

The Call Stack is a data structure which records basically where in the program we are. If we step into a function, we put it on the top of the stack. If we return from a function, we pop off the top of the stack. That’s all the stack can do.

Let’s see an example. Take a look at the following code:

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

When the engine starts executing this code, the Call Stack will be empty. Afterwards, the steps will be the following:

img

Each entry in the Call Stack is called a Stack Frame.

And this is exactly how stack traces are being constructed when an exception is being thrown — it is basically the state of the Call Stack when the exception happened. Take a look at the following code:

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

If this is executed in Chrome (assuming that this code is in a file called foo.js), the following stack trace will be produced:

img

Blowing the stack” — this happens when you reach the maximum Call Stack size. And that could happen quite easily, especially if you’re using recursion without testing your code very extensively. Take a look at this sample code:

function foo() {
    foo();
}
foo();

When the engine starts executing this code, it starts with calling the function “foo”. This function, however, is recursive and starts calling itself without any termination conditions. So at every step of the execution, the same function gets added to the Call Stack over and over again. It looks something like this:

img

At some point, however, the number of function calls in the Call Stack exceeds the actual size of the Call Stack, and the browser decides to take action, by throwing an error, which can look something like this:

img

Running code on a single thread can be quite easy since you don’t have to deal with complicated scenarios that are arising in multi-threaded environments — for example, deadlocks.

But running on a single thread is quite limiting as well. Since JavaScript has a single Call Stack, what happens when things are slow?

ps: 重点来惹

JavaScript是一个单线程的编程语言,这意味着它有一个简单的访问栈,来保证它可以在一段时间里做一件事。这个访问栈是一个数据结构,它基本上记录我们处于程序中所处的位置。如果我们进入到一个函数中运行,那么我们将该函数入栈,如果我们执行完了这个函数,从它里面返回,那么我们将这个函数出栈。这就是这个栈的工作。

接下来是一个例子,附的图简单明了地说明了访问栈的变化。

在这里有个堆栈帧的概念,就是指的是访问栈里面的单个栈元素就是一个堆栈帧

然后就是说利用堆栈信息,当发生错误的时候很容易就可以找到错误。(ps:yyds)

接着说堆栈溢出的问题,就是说访问代码没有终止条件容易造成溢出。

引入事件循环,说JavaScript很简单就能运行起来了,不用考虑那么多,但是因为JavaScript只有一个访问栈,要是运行慢了是不是就一直停下了?接着看吧

Concurrency & the Event Loop

What happens when you have function calls in the Call Stack that take a huge amount of time in order to be processed? For example, imagine that you want to do some complex image transformation with JavaScript in the browser.

You may ask — why is this even a problem? The problem is that while the Call Stack has functions to execute, the browser can’t actually do anything else — it’s getting blocked. This means that the browser can’t render, it can’t run any other code, it’s just stuck. And this creates problems if you want nice fluid UIs in your app.

And that’s not the only problem. Once your browser starts processing so many tasks in the Call Stack, it may stop being responsive for quite a long time. And most browsers take action by raising an error, asking you whether you want to terminate the web page.

img

Now, that’s not the best user experience out there, is it?

So, how can we execute heavy code without blocking the UI and making the browser unresponsive? Well, the solution is asynchronous callbacks.

This will be explained in greater detail in Part 2 of the “How JavaScript actually works” tutorial: “Inside the V8 engine + 5 tips on how to write optimized code”.

In the meantime, if you’re having a hard time reproducing and understanding issues in your JavaScript apps, take a look at SessionStack. SessionStack records everything in your web apps: all DOM changes, user interactions, JavaScript exceptions, stack traces, failed network requests, and debug messages.

最后主要是介绍一个场景:当程序引入了一些复杂的即时运算,JavaScript线程必须一直处理这个运算,造成浏览器渲染阻塞,页面没有响应的极差的用户体验和可能会造成浏览器奔溃的错误。通过这个场景来引入它的解决方法,异步回调 。以及打了个广告。

原文链接

目录
相关文章
|
4月前
Google Earth Engine(GEE)——当加载图表的时候出现错误No features contain non-null values of “system:time_start“.
Google Earth Engine(GEE)——当加载图表的时候出现错误No features contain non-null values of “system:time_start“.
94 0
|
13天前
|
C# C++
【Azure Function】在VS Code中创建Function项目遇见 No .NET worker runtimes found
【Azure Function】在VS Code中创建Function项目遇见 No .NET worker runtimes found
|
4月前
|
设计模式 前端开发 JavaScript
关于 SAP Fiori Elements List Report Go 按钮的实现
关于 SAP Fiori Elements List Report Go 按钮的实现
|
10月前
|
编译器 Go 开发工具
JetBrains GoLand 以debug运行Go程序时出现could not launch process: decoding dwarf section info at offset 0x0: too short报错之保姆级别解决方案
JetBrains GoLand 以debug运行Go程序时出现could not launch process: decoding dwarf section info at offset 0x0: too short报错之保姆级别解决方案
173 0
|
11月前
|
开发者
如何使用 ABAP Function Module SEO_CLASS_CREATE_COMPLETE 创建 ABAP class
如何使用 ABAP Function Module SEO_CLASS_CREATE_COMPLETE 创建 ABAP class
|
Go C++
VS Code安装go 插件报错处理
在命令行中设置如下go 变量,重启vscode 即可
97 0
|
Web App开发 JavaScript 前端开发
Selenium使用中报错:We\'re sorry but hr-frontend-v2 doesn\'t work properly without JavaScript enabled
Selenium使用中报错:We\'re sorry but hr-frontend-v2 doesn\'t work properly without JavaScript enabled. Please enable it to continue 这个错误提示表明目标网页要求启用JavaScript才能正常工作,而默认情况下,Selenium WebDriver是启用JavaScript的。如果遇到此错误,请按照以下步骤尝试解决问题
707 0
Selenium使用中报错:We\'re sorry but hr-frontend-v2 doesn\'t work properly without JavaScript enabled
|
程序员 Go Windows
【go 语言】解决 grpc:--proto_path passed empty directory name. (Use "." for current directory.)
【go 语言】解决 grpc:--proto_path passed empty directory name. (Use "." for current directory.)
199 0
Fiori elements执行过程解析:When click go in table list, odata service is sent
Fiori elements执行过程解析:When click go in table list, odata service is sent
Fiori elements执行过程解析:When click go in table list, odata service is sent