前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JavaScript基础——你真的清楚JavaScript是什么吗?

JavaScript基础——你真的清楚JavaScript是什么吗?

原创
作者头像
前端达人
发布2018-11-26 00:09:16
7440
发布2018-11-26 00:09:16
举报
文章被收录于专栏:前端达人前端达人

什么是JavaScript?

为前端开发,你是否问过自己或者思考过什么是JavaScript吗?JavaScript有什么特点?如果让你让一句话高度介绍,你会怎么说?小编认为,在你想深入一门语言,必须要清楚理解这们语言有什么特点和其中的运行机制,这是学好一门语言的基础。

JavaScript是一个单线程、非阻塞、异步、解释性语言。

单线程是个什么鬼?

有计算机基础知识的同学可以忽略这部分内容,首先我们来一起了解下计算机基础知识:线程和进程

打个比方,我们去超市购物,结账的时候会有多个收银窗口,这样的好处就是在同一时间完成更多交易处理。这就是计算机常说的多并发概念,操作系统是多并发执行任务,因为它同时运行多个进程。进程是执行环境或正在运行的应用程序的实例。例如,你可能一边浏览着网页、一边打开编辑器写着代码、一边开着微信聊着天,这都要归功于计算机能同时运行多个应用进程。

应用程序也是可以处理多并发的,主要是靠线程实现的。在其他高级语言,如果你熟悉JAVA就会很容易理解,JAVA可以轻松创建多个线程处理并发问题,比如同时处理发出HTTP请求,查询数据库或打开文件。但是JavaScript是单线程的运行环境,它有且只有一个调用栈,它每次只能做一件事,程序每次只能运行一段代码,这就是单线程。单线程更通俗的解释就是——所有任务需要排队,前一个任务结束,才会执行后一个任务。如果前一个任务耗时很长,后一个任务就不得不一直等着。

什么是调用栈?(call stack)——代码在运行过程中,会有一个叫做调用栈(call stack)的概念。调用栈是一种栈结构,它用来存储计算机程序执行时候其活跃子程序的信息。(比如什么函数正在执行,什么函数正在被这个函数调用等等信息)。调用栈是解析器的一种机制。

首先一起看下一段简单的代码,我们先了解下Javascript是如何运行的?

首先按照函数调用的顺序进栈,然后函数执行完了,将值传给下个函数,出栈,最后将结果输出。

阻塞是个什么东东?

什么是阻塞,没有严格的定义什么是阻塞。仅仅是指代码运行得很慢,比如说console.log不慢,遍历从1到10亿次很慢,你可以可以暂且想想下,如果你用浏览器打开一个网页,一个网页肯定会涉及到各种数据的请求,图片、接口数据、CSS文件之类,如果JavaScript不想办法解决优化单线程加载数据问题的话,我们浏览网页的体验可能是这样的:先出来一个空白页面,过了一会一张图片出来了,然后在出来一段文字,过了一会接口数据读取完了,显示了一段文字,就这样网页像挤牙膏似的一点点的显示出来,这样的浏览体验你还会看网页吗?。因此更白话点在栈里表现很慢的东西都叫阻塞。

就像下图的代码,小编写了一个自己调用自己的函数,让函数进入无线循环的过程,造成了调用栈里需要执行大量的函数,模拟了一个阻塞,浏览器实在无法承受调用之痛,报错了!

秘密武器——非阻塞、异步回调

由于JavaScript要解决这个问题,必须要突破单线程的瓶颈,“异步回调”就成为JavaScript的秘密武器,完美的解决了此问题。异步回调让其拥有了“多线程”的能力,其实并不其然,异步回调是怎么解决并发问题,阻塞问题,不知道各位思考过背后的运行进制吗?

维基百科是这么解释回调函数的:回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用为调用它所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

通俗点回调是一个函数被作为一个参数传递到另一个函数里,在那个函数执行完后再执行。有点不好理解,小编在说的直白些就是——B函数被作为参数传递到A函数里,在A函数执行完后再执行B。

了解完异步回调的概念后,我们来看看JavaScript是如何运行的?首先看看下面一张图

在介绍这张图时,我们先了解下什么是任务队列——所有任务可以分成两种,一种是同步任务(synchronous),另一种是异步任务(asynchronous)。同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;异步任务指的是,不进入主线程、而进入"任务队列"(task queue)的任务,只有"任务队列"通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

主线程从"任务队列"中读取事件,这个过程是循环不断的,所以整个的这种运行机制又称为Event Loop(事件循环)。上图中,主线程运行的时候,产生堆(heap)和栈(stack),栈中的代码调用各种外部API,它们在"任务队列"中加入各种事件(click,load,done)。只要栈中的代码执行完毕,主线程就会去读取"任务队列",依次执行那些事件所对应的回调函数。

"任务队列"是一个先进先出的数据结构,排在前面的事件,优先被主线程读取。主线程的读取过程基本上是自动的,只要执行栈一清空,"任务队列"上第一位的事件就自动进入主线程。但是,由于存在后文提到的"定时器"功能,主线程首先要检查一下执行时间,某些事件只有到了规定的时间,才能返回主线程。

通过下图将异步函数的执行步骤可视化,让我们更加容易理解上诉文字内容。

今天的介绍就到这里,想必大家都十分清楚JavaScript的特点了,我们一起了解什么是单线程、进程、阻塞、调用堆栈、异步回调、任务队列、事件循环等概念,同时又清楚了JavaScript的运行机制,今天的内容大家都学会了吗。接下来小编将会给大家介绍JavaScript回调,承诺和异步函数,没理解的同学建议在反复看下,没关注公众号的,麻烦大家关注微信公众号“前端达人”

注本文内容参考视频 Philip Roberts的演讲《Help, I'm stuck in an event-loop》 https://www.youtube.com/watch?v=8aGhZQkoFbQ

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是JavaScript?
  • 单线程是个什么鬼?
  • 阻塞是个什么东东?
  • 秘密武器——非阻塞、异步回调
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档