这个问题已经有不少人回答过了,其中不乏一些大牛,接下来我做为一个草根来发表一些我的的见解:php
一、地址输入过程css
地址栏能够抽象成一个文本输入域对象,Chrome应用程序内必定给该对象绑定了键盘输入的回调,该回调将交给操做系统,操做系统会在用户按键时执行全部应用传递给它的回调队列,当操做系统监听到用户按下了回车键而且在回调队列遍历执行到Chrome浏览器传递给操做系统绑定的回调时,开始解析地址,Chrome会调用网络模块对地址进行解析,将其中的应用层协议、主机、端口、虚拟目录、文件名、参数、锚等各部分解析出来。html
二、DNS解析前端
当发现主机部分不是以IP形式表示时,就会试图去寻找该主机的IP,在此说一些废话来解释下为何要找IP,由于IP是网络中每台计算机的惟一标识,计算机采用IP做为惟一标识而没有采用域名做为惟一标识,我的感受缘由是由于计算机更擅长处理数字,而数字不易于被人类所记忆,所以诞生了DNS域名解析系统html5
咱们本身的PC和手机中其实都运行着DNS客户端,若是运行在用户主机上的某些应用程序(如Web浏览器或者邮件阅读器)须要将主机名转换为IP地址时,也就是咱们如今的状况,这些应用程序将调用DNS的客户机端,并指明须要被转换的主机名。mysql
DNS客户端拿着这个主机名依次从本地hosts文件、本地DNS解析器缓存、本地DNS服务器、13台根DNS服务器、一级域名服务器、二级域名服务器...此外,DNS是应用层协议,全部DNS请求和回答报文使用的UDP数据报通过端口53发送。总之咱们最终能够拿到目标主机的IP地址jquery
三、浏览器http数据包到客户端网卡css3
内部应该是经过一个对象(相似于XMLHttpRequest对象)将要传递的数据进行封装,具体的数据包格式以下:git
调用系统函数socket,将该请求交给传输层,因为http是基于TCP来传输的,所以传输层协议是TCP协议,刚才封装好的http数据包将做为TCP段的数据部分,TCP段的头部封装了源端口和目标端口github
接下来TCP段会交给网络层,网络层使用IP协议,网络层将整个TCP段做为IP数据包的数据部分,IP数据包的头部封装了源主机IP和目标主机IP
这个IP数据包接下来进入数据链路层,数据链路层将整个IP数据包做为数据帧数据部分,数据帧的头部封装了源主机MAC地址和下一跳路由的MAC地址,若是是第一跳,能够理解为网关的地址,源主机和各个路由器一般经过广播的方式学习到下一跳路由器的MAC地址
封装好的数据帧经过物理层(网卡驱动)转换为二进制字节再进行传输
四、客户端到服务器端
电脑的网络适配器(也就是网线接口)能够链接交换器或路由器,而后再连调制解调器(猫)转变为模拟信号
我的感受模拟信号从电话线、光纤、网线出去以后在路由器之间作转发时在各个路由器节点中也被转变为了数字信号,而后分析处理完再转变为模拟信号再转发
五、服务器接收到数据并将各层头部拆解再交给服务器应用程序处理
服务器网卡接收到浏览器发来的二进制字符序列,网卡驱动程序分析其目标Mac地址,从而判断是否该接受该数据包,肯定接收该包以后再交给传输层进一步取出端口信息,从而肯定该包到底要转给应用层中哪一个应用程序,在此,目标端口是80,若是服务器的80端口处于开启状态(监听状态)则将该数据包交给该服务器应用程序(Apache Nginx等)作进一步分析
对于规模很是小的应用,这台主机极可能承担了全部角色(应用服务器、文件服务器、数据库服务器)
稍微成点规模的应用都会在此布一台反向代理服务器,根据Request URL头和Remote Address头和必定的算法(例如轮寻)对请求进行转发,转发到多台服务器作负载均衡,这样一来这台作转发的服务器访问量就是转发到的那些负载均衡服务器的访问量的好多倍,这也就要求这个服务器可以承受很大的并发量,这种可以承受很大并发量的服务器的典型表明就是Nginx。代理服务器转发到的负载均衡服务器一般是应用服务器,所谓应用服务器就是咱们的后台程序(Java PHP Node)所存放的服务器,后台程序访问数据库是常有的事,而数据库一般不会和应用服务器放在一块儿,执行这些高级语言编译成的机器指令必然对CPU和内存有着很高的要求,而数据库其实本质就是一种特殊的文件系统,所以数据库读写本质上就是对文件的读写,文件读写必然对机器的I/O接口(硬盘读写)性能有着很高的要求,可见应用服务器和数据库服务器有着不一样的需求,所以术业有专攻,两者一般不会放在一块儿,同理应用中的图片、音频、视频等文件道理也同样,有专门的处理这些文件类型的设备,所以在有条件的状况下也会分开存放在不一样的文件服务器上。
当数据访问量大到一台数据库服务器、一台图片服务器、一台音频视频服务器...不能知足需求时,咱们并不该该想着换一台性能更好的服务器,而是再配置一台和第一台服务器性能差很少的服务器,同时和多台应用服务器为用户提供服务的道理同样,分布式集群一般是解决网站高并发、海量数据存储的问题的惯用手法。
将目光再转向数据库,例如新浪微博的服务器,那些明星大腕的微博帐号中存储的数据访问量和咱们凡人的数据访问量相比必定不是一个级别,这就形成了数据库访问的不均衡问题,80%的访问量都集中在20%的数据上,这时缓存就应运而生了,对于缓存有两种处理方案,一种是直接缓存到应用服务器的内存中,这样应用服务器能够很是快速的访问到数据再作出响应,但问题是自己应用服务器的内存就紧张,再加上缓存的竞争,显然不合适,因而分布式缓存服务器就诞生了,即专门拿出一台或多台内存超大的服务器作缓存存储器,目前比较流行的缓存应用有redis。
固然这以后问题还没完,由于虽然能够经过从缓存中读取数据把压力降下来,可是对数据库的写操做依然无动于衷,一般的作法是配置数据库服务器的主从关系,写操做发生时应用服务器访问主服务器,而后作主从复制。当咱们的应用涉及到的用户遍及全中国时,还能够架设CDN服务器。。。
稍微扯的远了一些,一般应用服务器也称为主服务器,主服务器接收到http数据包时,会取出Request URL,若是Request URL有值,则去找它对应的虚拟主机,再去找虚拟主机所映射的真实路径,从而找到服务器端项目目录
若是直接经过IP地址访问,则会找默认应用
六、应用服务器对请求的处理过程
在传统的后台渲染架构中,一般会根据请求的虚拟路径例如/User/User/getUserList,定位到某个服务器端脚本过程
对于虚拟路径,服务器端有专门的入口文件和配置文件进行处理,若是后台采用典型的三层架构的话,对于index.php/User/User/getUserList,一般表明找到User模块下的UserController的getUserList方法,首先实例化UserController类,经过获得的实例化对象调用getUserList方法,该方法可能还会实例化模型UserModel类,模型类一般会读写数据,数据源有多是缓存,也有多是数据库,缓存和数据库都有可能放在不一样的服务器中,所以还可能要创建到数据源的链接,链接过程和浏览器请求差很少,若是向redis缓存取数据的话传输层TCP段的头部源端口和目的端口应该是80和6379(可能会出于多实例和安全性的考虑将其改成7200),若是向mysql存取数据的话传输层TCP段的头部源端口和目标端口应该是80和3306,所以UserModel实例化对象应该有从数据源中取出全部user信息的方法,这样,Model拿到数据,再将其返给Controller,Controller拿到这个数据以后一般会引进来一个模板,对象拿到的数据一般会做为模板变量传进去,这样本来静态的html页面就由于模板变量的介入而变成动态页面,这个模板这样动态化了以后就会将其返回给浏览器,这种情形下浏览器拿到的将是一个处理好了部分数据的html页面,将直接塞到页面中去
注意咱们刚才提到了浏览器拿到的是一个处理好了部分数据的html页面,为何是部分数据呢?由于浏览器是要和用户交互的,在服务器端怎么能知道用户有什么动做呢?例如咱们下面列出来的这个省市联动的状况:
注意到,咱们只是把全部的省份循环出来了,但并无把城市循环出来,缘由也很简单,中国有34个省级行政单位这个毋庸置疑,但问题是城市总得是某个省下面的,具体哪一个省是要根据用户的选择来加载的,而用户的选择这个操做必定发生在浏览器端,而咱们渲染的这一步发生在服务器上,怎么可能知道选择了哪一个省呢,因此这部分数据并无渲染,而是等用户作出选择以后异步的经过ajax告诉服务器用户选择了哪一个省,再加载对应的城市数据,咱们在此提到了异步加载,所谓异步加载也就是说只是发一个请求让服务器返回城市对应的数据,浏览器拿到这个数据以后将id为city的select填充满该省下辖的城市,注意在此期间province部分的select数据并无动,即浏览器和服务器都没有从新去渲染,在此值得一提的是,在ajax诞生以前(1998年之前),不论用户作什么操做都会向服务器发一个请求,包括咱们这里的获取城市数据,这种状况下option里面可能还套了一个a连接,当选择了一个省以后直接刷新页面,服务器从新把省、市的数据从新渲染一遍一并返给浏览器
早期业务不太复杂,数据量小的时候这么作彻底没问题,可是后来浏览器端的操做愈来愈多,操做一次请求一次服务器,请求的次数也就愈来愈多,服务器压力愈来愈大,还有典型的场合是表单校验,浏览器端用户即便什么都没填(不须要服务器端的任何帮助就知道这表单必定是错误的)也向服务器发请求,事无巨细的请求服务器。。。终于异步的概念被提了出来,Javascript在被沉寂了遗忘了多年以后被人拾起来,在此以前Js仅仅就是在页面上弄个点击隐藏显示、图片轮换等微不足道的事情。
刚才咱们说到这是传统的后台处理方式,异步的引入的确让服务器端性能有所好转,可是用户的要求在慢慢变高,所以这样作还远远不够,咱们但愿尽最大可能的减小服务器的压力,能交给客户端处理的就交给客户端处理,毕竟人多力量大,假如1万人同时请求一台服务器去渲染一个全部省份的select,服务器要渲染1万次,所以近几年又诞生了一种新的处理方式就是客户端渲染,咱们经过URL仅仅是请求服务器返回一个空的页面:
这个空的页面一加载完成,立刻再向服务器发一个请求,请求全部省份数据,注意这里的省份的数据是json的格式,和上面说的返回一个拼接成的html串相比数据包长度减少了不少
所以,当一样有1万人请求服务器时服务器所作的处理要简单不少,只需单纯的返回从库里取出的数据便可(一般会转换为json形式)
固然这样作的同时,就会发现浏览器端在ajax的success回调中仅仅拿到了一个很是轻量的json,接下来的操做(操做DOM)由浏览器本身处理,不过浏览器给提供的dom接口很是底层,并且设计极其反人类,还有诸多兼容性问题,所以浏览器端的处理逻辑将会变得很复杂,最开始的时候搞后台的大神们不觉得然,感受这些浏览器端的删删改改的处理没什么了不得的,复制粘贴抄起家伙就干,等到干的时候感受各类不爽。。。后来的后来,在2008年左右,终于诞生了web前端工程师这个岗位,这个岗位主要的任务就是专门来处理浏览器客户端的各类交互。还拿我们刚才的这个省市联动的例子,在获取省份或城市数据成功了以后前端拿到了省份或城市的数据,而后再调用浏览器提供的操做DOM的API建立一个个option,而后再附加到select中去,前面提到浏览器端给提供的DOM接口很是底层,并且还不太好用,兼容问题又多,更重要的是前端每天都在干这些事,写的多了天然以为不爽,因而便出现了jquery一统前端江湖的局面,能够说作前端的人jquery都是必备的基本技能,固然jquery的学习门槛很是低,并且处理了全部的浏览器兼容问题,还提供了链式调用的方便写法,并且jquery提供的功能也特别丰富:强大的选择器、链式操做、事件绑定、ajax、动画函数,比较高级一点的API有函数队列、延迟对象、数据缓存等等。所以直到今天,jquery依然很火爆
而随着时间的推移,前端处理的数据毫不是像省市联动这种小儿科的东西同样那么简单了,愈来愈多的业务逻辑放在前端,jquery慢慢显露出它的不足,例如咱们须要渲染下面这种形式的一个表格:
每趟列车的数据确定是一个很大的json,而后放着列车的信息,用js写出来以后效果和下面这种的差很少:
能够看到,这段代码不只包含了dom操做,还绑定了事件,事件里面又有一些效果,有些a链接还跳到一个新页面,有些地方还须要再经过ajax获取更详细的信息。。。整个一坨代码就像一个大杂烩,乱七八糟。虽说能够封装一个函数把各个功能打散,可是就以我我的经从来看,这种开发模式下单个文件写个三五千行、最顶上的全局变量定义个十几二十个都是常事,后期的维护更是一场噩梦。
这样的问题不光是像我这样的草根遇到了,全世界的前端都面临这样的问题,终于,在2009年,Google公司内部某个项目在用传统的jquery开发模式下代码写了17000多行,而其中一位叫Misko Hevery的前端工程师就提出了改造它的想法,如今看来我我的认为这位大神的整体思想是把后台渲染的思路拿到前端来,也就是用Js这门语言写了一个html的编译器。固然回想起后台渲染的那个页面,我我的惟一的感受就是不三不四,由于页面中有一部分数据是后台渲染好的,还有一部分和用户交互的数据是前端js加上的,这样一来这个html页面就通过了后台和前端两种人之手,除了在交互方式上感受各类不爽以外,在后期维护中这是典型的灰色地带,出现问题责任没法明确分清、相互推脱。而这位大神的伟大之处就在于把数据渲染和用户交互进行了统一,一并划到前端来处理,从处理的方式上看感受很是流畅,这个思路就是Angular框架的前身
以前个人一位40多岁高龄的老大曾经这样跟我说过使用Angular和使用Jquery的区别:Jquery仅仅是把原生的API封装了一下,说白了就是个库函数,并无达到框架的做用,而Angular是真正改善Js代码结构的真正意义上的框架。用了Angular以后,上面12306的那个例子就能够写成:
和以前的Jquery开发方式相比实在是好了太多
Angular的出现我我的认为具备划时代的意义,由于它把前端再一次推上了一个新的高峰,此后的2013年Facebook发布了React,2015年尤雨溪发布了Vue,实际上都是对于DOM渲染提供的一种新的处理思路,例如React推崇经过组件化的方式来组合web项目,而Vue则是把Angular和React结合在了一块儿,可是Angular绝对是具备开创性意义的一个框架
固然Angular并非一点缺点都没有,首先使用Angular的项目几乎都作成了单页面应用,而单页面应用的首屏加载了全部的Controller Directive Services以及各类库,所以首屏性能极差;其次,因为数据都经过Js渲染,对于SEO来讲很是不友好;再者,Angular1对于移动端支持的不太好,我我的以前在公司作过一个Angular+Ionic的webapp,最后的体验是卡到爆
对于Angular和React的学习成本,门槛的确很是高;而Vue以其简单易学的API、上手较快的特色在github上的star数正在猛增,可是我我的仍是认为每一个框架的出现必然有它的历史意义,确定是应运而生的,所以无所谓哪一个框架好,哪一个很差,只是适用的场合不太同样而已,当前前端的框架至关之多,就以我工做的这几年内接触过的大大小小的库和框架绝对超过二三十种,库和框架永远都学不完,所以我我的感受学习框架内部的API设计思路,学习它经过什么方式解决了什么问题,这才是学习框架的关键所在
对于Angular的缺点我我的以为不过重要,由于适合作单页面应用的项目每每对SEO的要求不过高,而性能的问题经过按需加载以及压缩、合并代码减小请求次数,下降请求量也能够从必定程度上避免,并且首页性能差换来的是接下来各个页面良好的用户体验,Angular二、React和Vue已经提出了SSR(服务器端渲染)的思路来解决这些问题了。
Angular2已经对这些问题有所改善,期待ECMAScript6普及的那一天,Angular会再次辉煌起来,固然Angular2的学习门槛更高,Angular1和Angular2的区别基本上是象牙和象牙塔的区别。
七、数据到浏览器中的处理过程
事实上咱们能够猜想一下浏览器内部的工做流程:应该是在地址栏中的值改变时(因为用户的输入或者页面的跳转)调用相关的接口去获取数据,例如若是地址栏中输入了file:///C:/Users/lenovo/Desktop/attrtest.html,浏览器应该就会去本地对应目录下寻找attrtest.html文件,地址栏中若是输入了https://www.baidu.com/,浏览器使用http或https等应用层协议对数据进行解析,再去网络中寻找对应的数据,根据响应头中提供的数据类型(Content-Type响应头)分别作不一样的处理,接下来解释一下当经过http或https协议获得的数据中Content-Type响应头获得的类型是text/html时或经过file协议取到了html类型的文件时所作的处理:
根据HTML结构构建DOM树,根据CSS结构构件render树,遍历这两棵树各个节点而后向页面中渲染
遍历两棵树的节点过程当中,若是发现连接属性,例如DOM树中link标签的href,img的src,script标签的src,video和audio标签的,css3自定义字体加载的文件,以及render树种background属性的url,会再开新的请求去请求对应的资源
我的感受:link标签的href、script标签的src加载完以后触发DOMReady事件(DOMContentLoaded和onreadystatechange),当图片、视频、音频等资源加载完时触发onload事件
实际上浏览器拿到一个html页面以后解析全部的html、css、js的操做其实就是对一组DOM节点对象及其属性(其中典型的就是style属性)的增删改查操做
至于说浏览器内部究竟是如何渲染页面的,如何将一个个div根据匹配的css样式生成一个个DOM对象,这些DOM对象在C++类或结构体中是怎么表示的,都有哪些属性哪些方法,如何渲染到页面中的,我我的还在学习中,等后期学完C++,看了必定的webkit和V8的源码以后再来补充。在此极力推荐这篇文章:how browsers work
在此格外要提一下JavaScript的执行流程,咱们从宏观到微观的顺序来讲明:
浏览器拿到一个html页面以后可能会遇到好多个script标签,无论这些script标签放到哪里,老是落后于css的执行,换句话说,若是css和Js分别对某个节点的某个样式进行操做,无论css写在了Js的前面仍是后面,CSS老是会优先于Js执行:
结果发现div是绿色的
浏览器在解析每一个script标签时会作判断,判断它有没有src属性,若是有的话就从新发起请求,请求src值对应的脚本资源,不然查看script标签内部是否有脚本,找到脚本以后执行,若是在一个script标签上既加了src又在标签内部写了一段脚本,则只去加载远程脚本资源,而标签内的脚本不会执行,如下代码myj变量找不到,所以会报错:
能够猜想,浏览器在加载执行js的时候是同步的,例如对于下面这段代码
最开始遇到第一个script标签,发现它带有src,那么浏览器会将其下载完,紧接着再解析该段脚本,而后再往下走,发现第二个script标签,没有src属性,因而就直接执行里面的脚本,因为阻塞加载,后面的script才能够用到前面从远程加载来的jquery脚本中定义的变量$
这种阻塞加载的机制在html5中作出必定改观:html5为script标签新增长了一个属性:async,该属性表明script标签里面的内容是否要异步加载
若是 async 属性为 true,则脚本会相对于文档的其他部分异步执行,这样脚本会在页面继续解析的过程当中执行。
若是 async 属性为 false,而 defer 属性为 true,则脚本会在页面完成解析后执行。
若是 async 和 defer 属性均为 false,那么脚本会当即执行,页面会在脚本执行完毕后继续解析。
JavaScript是一个单线程执行的指令序列,每一个script标签内的代码会分别被浏览器解释,虽然有变量的提高,可是后面的script标签中定义的变量不会提高到前面的script标签中,这一点要格外注意,例以下面的代码中第一个script标签里面console.log(a);是要报错的
可是后面的script代码块可使用前面的script代码块中定义的变量,由于它们都做为属性挂在了全局对象window上,例如:
函数的提高也是一样的道理
Js中一切接对象,数组、json、本身定义的构造函数实例化以后的对象天然没必要多说,函数也是对象,就连数字、字符串、布尔这些基本类型的值也能够当作是对象,我我的对对象的理解是对象是一个属性和方法的集合,咱们能够经过点和中括号的形式来对对象进行set或get的操做,咱们能够经过下面这几个例子来证实这个观点:
这个例子中咱们把js中几种典型的对象列了出来,并分别定义了各类类型的对象,并且经过点或中括号的方式访问或设置了对象的属性或方法,这里有几点须要咱们注意:
一、对于基础类型的对象(数字 字符串 布尔),在set/get属性和方法时浏览器会生成一个临时对象,set/get操做结束后该对象被回收,而复合类型的对象会在其所处的做用域可用的时间段内常驻于堆内存中,所以复合类型的对象在js中又叫引用类型,也就是说在其所处的做用域可用的时间段内经过指向它的各个指针对其进行修改时修改的都是一个东西,同时,若是指向该对象的指针被赋值为其余值,该指针就不指向该对象了,也就不能经过该指针访问对象中的属性和方法了,同时咱们也能够猜想,浏览器内部的垃圾回收机制中有可能会监听指向该堆空间的指针,若是没有指针指向该堆空间了,那该对象也该被回收了
二、咱们像上面那个样子写,好比var a = 1; var arr = [1,2,3]; function fn(){},其实本质上就是在建立对象,分别建立数字类型的、数组类型的、函数类型的对象。而咱们同时也能够看出,对象是分“类型”的,而实际上咱们在建立每一个对象的时候,都会默认建立一个名为constructor的属性,该属性值为函数类型。其实,JavaScript给咱们提供了一种经过构造函数建立对象的机制,例如我想建立一个数组类型的对象除了能够经过var arr = [1,2,3];的方式,还能够经过var arr = new Array(1,2,3);这种构造函数的方式;再如,咱们建立一个普通对象除了能够经过var obj = {a: 1};的方式,还能够经过var obj = new Object();obj.a = 1;这种构造函数的方式,而构造函数这种方式其实是更为通用的一种方式,由于咱们能够自定义一个构造函数来建立咱们本身想要的一种对象类型,再去实例化该类型从而建立该类型的对象。而咱们同时也能够猜想,浏览器内部其实是把var obj = {a: 1};和var obj = new Object();obj.a = 1;这两种建立对象的方式作了相同的处理,可能在词法分析阶段不一样,可是在语法分析构成AST、中间代码、目标代码生成阶段的处理应该是彻底一致的,而之因此出现var obj = {a: 1};这种定义对象的方式是由于咱们常常须要定义这种对象,而每次new Object这样写太过于繁琐,所以这其实就是浏览器给咱们提供的一种建立对象的简便写法而已
三、经过上面的分析,相信你们对对象已经有了一个初步认识,那么对象与对象之间必然不是独立的关系,它们之间必定存在着某种关联,没错,确实是这样,首先咱们考虑这样一种情景:对于数组,全部数组对象都有push pop等方法,若是在每一个对象所属的堆内存空间中都给他们分配各自的push pop空间,这就有点太浪费了,由于无论是哪一个数组对象,push和pop的操做时彻底同样的,根本不必一人一份,所以这些东西必定要共享才能够。实际上当咱们每次建立一个对象时,该对象会自动建立一个__proto__属性,这个__proto__属性就指向该对象的原型对象,经过刚才的分析,相信你们已经猜到,所谓原型对象,其主要功能就是存放一类对象的公共部分属性和方法的对象,其实咱们还能够猜想,实际上全部的对象是否是都有一些公共的方法呢,没错,实际上全部的对象都有两个方法:valueOf和toString,咱们不可能在每一个对象的堆空间中存放这两个方法,若是在各类类型对象的原型对象所处的堆空间中存放valueOf和toString这两个方法的话彷佛也有一些浪费,毕竟原型对象有可能也挺多的,因而,更进一步的抽象思路来了:原型链,原型对象也是对象,原型对象也能够有原型,所以原型对象的__proto__还能够再往上指,那么最上面的那个对象是谁呢?就是Object.prototype,这个对象就没原型了,由于已经到头了。
能够看出原型是同类对象的一个公共对象,这些对象的__proto__属性都指向它,而构造这一类对象的也是同一个构造函数,由此咱们能够猜想:构造函数和原型对象之间有什么关系吗?确定是有的:构造函数有一个prototype属性,这个prototype属性就指向经过这个类实例化建立出来的对象的原型对象
对象能够经过constructor访问到建立本身的构造函数
综上,联系对象之间的桥梁是——原型(即对象的__proto__属性)
其实Js中继承的原理就是咱们刚才分析的这些:
在inheritPrototype函数内部咱们明显发现咱们将子类subType的prototype指向F实例化对象,而F类的prototype已经被咱们修正成父类的prototype了,所以至关于咱们的子类指向了父类的prototype,天然能够访问父类prototype上的方法了
固然对象自身身上的属性继承的时候还须要借助call和apply
四、在浏览器的环境中实际上已经建立了不少内置对象了,具体有哪些内置对象就不一一阐述了,能够参考下图:
接下来是我我的对函数对象的一些看法:因为函数也是对象,那么函数自己也必定是属性和方法的集合,理解这一点能够参考经典的面向对象语言——Java的设计:Java中类也有方法和属性,被称为类属性和类方法(或者静态属性和静态方法),既然如此,能够猜想在Java虚拟机内部对类和类的实例必然有一些相同的处理手段,再进一步抽象一下,能够猜想类也是一个特殊的对象,固然等后期对Java比较熟悉以后再看一下深刻理解Java虚拟机这本书以后再过来补充
关于对象的话题暂且先说这么多,接下来进入下一个话题,做用域:
能够猜想在浏览器引擎内部,做用域是实实在在的对象,只不过在Js中它为咱们隐藏了做用域的细节
2017年6月3日编辑====================
在ECMAScript5以前,js中只有两种做用域:全局做用域和局部做用域(函数在执行时生成的做用域),函数执行时会生成一个新的做用域对象,并在栈上开一块新的私有空间用于存放当前该函数中各个变量,当函数执行结束时,做用域对象被回收,栈上的私有空间也被释放,这是正常的函数执行的结果。可是有种不正常的状况——闭包:当一个函数在执行完以后最后返回来一个函数供外部调用,并且该返回值函数中还访问到了父函数中的某个变量,那么即便父函数执行完了父函数中的这个变量也还会驻留在内存中不会释放,例如:
这个案例中的变量a就在函数closure执行结束以后一直驻留在内存中,由于外面innerFn函数还会调用到它,而正由于一直在内存中,因此每次均可以对同一块内存空间操做,因此console出来的a的值每次都会变
实际上函数内部并不必定非得返回函数类型的值才叫闭包,只要返回回来的东西用到了父函数的变量那都叫闭包,例如能够返回回来一个对象,对象的某个方法调用到了父函数的某个变量,这种状况其实也是闭包,例如:
callback函数内部_callbackCache变量其实在callback执行完以后也不会被释放,由于返回的对象在外部调用其add方法时会用到这个变量,实际上这种思路在jQuery以及Angular内部用的很是多,例如jQuery内部的数据缓存管理、队列管理、回调函数、延迟对象等等,Angular里面把全部注册的模块都放到一个闭包变量中,把每一个模块下绑定的constroller、directive、service、provider也放大对应的闭包变量中等等,就不一一举例了
参考连接:
一、DNS解析的过程是什么? https://www.zhihu.com/question/23042131
二、当时发生了什么? https://github.com/skyline75489/what-happens-when-zh_CN
三、网卡(网络适配器),猫(调制解调器),路由器三者有什么区别? https://www.zhihu.com/question/27142839
四、WAN口和LAN口有何不一样 https://zhidao.baidu.com/question/180687224.html
五、路由器与交换机的本质区别 http://jingyan.baidu.com/article/8065f87fe57f372330249851.html
六、常见的网站服务器架构有哪些? https://www.zhihu.com/question/20657269
七、图解正向代理、反向代理、透明代理 http://z00w00.blog.51cto.com/515114/1031287
八、从输入 URL 到页面加载完成的过程当中都发生了什么事情? http://fex.baidu.com/blog/2014/05/what-happen/
九、浏览器内部工做原理 http://kb.cnblogs.com/page/129756/
十、Javascript的执行过程详细研究 http://blog.csdn.net/cxiaokai/article/details/7552653
十一、HTML属性与DOM属性的区别? https://segmentfault.com/q/1010000004100696?_ea=489898