javascript的加载、编译、线程

一. Js嵌入网页的三种方式:

1.script标签对,将代码块写入进去;

2.加载外部脚本

<script src="example.js"></script>

如果脚本使用了非英文字符,还需要注明charset;

<script charset="utf-8" src="https://7n.w3cschool.cn/attachments/image/cimg/pre>

3.行内式,直接写进html代码,不利于代码管理不建议

<div οnclick="alert('Hello')">

</div> <a href="javascript:alert('Hello')"></a>

二. 正常的网页加载流程:

  • 浏览器一边下载html,一边解析;
  • 解析过程中发现script标签;
  • 暂停解析,下载script标签的外部脚本
  • 下载完成,执行脚本
  • 恢复继续向下解析html网页

因为script标签会出现阻塞,所以放在最下面,好处就是如果在dom生成之前就调用dom,js会报错,如果脚本在尾部加载,dom已经存在,不会影响了

还有一种方法就是使用DOMContentLoaded,等dom完成再调用js方法

<head>
  <script>
    document.addEventListener("DOMContentLoaded", function(event) {
    console.log(document.body.innerHTML);
  });
  </script>
</head>

还有一种方式就是使用script标签的onload属性,方script标签指定的外部脚本下载和解析完成会触发一个load事件,将要执行的代码写在这个时间内的回调函数中

<script src="jquery.min.js" οnlοad="console.log(document.body.innerHTML)"> </script>

三.多脚本加载

当存在多个script标签时候,浏览器会平行下载1.js和2.js,但是执行会先执行1.js再执行2.js,和谁先下载完无关,脚本的执行顺序由它的书写顺序决定,当然会出现阻塞效应,加载完之后,浏览器才会积蓄进行页面渲染。

同域,不同域的资源

对于同一个域名的资源,比如js,css,img等文件,浏览器一般最多同时下载6个,

如果是来自不同域名的资源,就没有这个限制,所以通常把静态文件放在不同域名之下,以加快下载速度。

四.defer属性解决js脚本阻塞渲染的问题

<script src="https://7n.w3cschool.cn/attachments/image/cimg/script>

<script src="2.js" defer></script>

在script标签中加入defer属性后网页的运行机制变化:

  1. 浏览器开始解析html网页
  2. 解析过程中,发现带有defer属性的script标签
  3. 浏览器积蓄向下解析html网页,同时并行下载script标签的外部脚本
  4. 浏览器解析完所有的html,此时再执行下载的脚本

兼容性:支持性不好,ie9及以下版本会出现2.js不一定会再1.js之后执行,如果需要支持老本ie,不建议用这个方法。

注意:对于内置而不是连接外部脚本的script标签,以及动态生成的script标签,defer属性不起作用。

五.Async属性解决js脚本阻塞渲染的问题

<script src="https://7n.w3cschool.cn/attachments/image/cimg/script>

<script src="2.js" async></script>

在script标签中加入async属性后网页的运行机制变化:

  1. 浏览器开始解析html网页
  2. 解析过程中,发现带有async属性的script标签
  3. 浏览器积蓄向下解析html网页,同时并行下载script标签的外部脚本
  4. 脚本下载完成,浏览器暂停解析html页面,开始执行下载的脚本
  5. 脚本执行完毕,浏览器恢复html网页解析

兼容性:支持性不好,ie10及以上版本支持

缺点:无法保证脚本执行顺序,谁先下载完谁先执行

defer属性和async属性到底应该使用哪一个?一般来说,如果脚本之间没有依赖关系,就使用async属性,如果脚本之间有依赖关系,就使用defer属性。如果同时使用async和defer属性,后者不起作用,浏览器行为由async属性决定。

 

六. 脚本动态嵌入

特点:动态嵌入必须等css文件加载完成后,才会去下载外部脚本文件;

静态加载就不会存在这个问题,script指定的外部脚本文件,都是与css文件同时并发下载

好处就是:动态生成的script标签不会阻塞页面渲染,不会假死,

缺点:无法保证脚本的执行顺序,哪个脚本先下载完就先执行哪个

解决:设置async 设置为false

['1.js', '2.js'].forEach(function(src) {
  var script = document.createElement('script');
  script.src = src;
  script.async = false;
  document.head.appendChild(script);
});

以上代码不会阻塞页面渲染,且可保证2.js在1.js之后执行,不过在这段代码后加载的js文件,需要等待2.js执行完之后执行

加载使用协议:

如果不指定协议,example.js浏览器默认采用http协议下载。

如果使用https协议下载,必须写明(前提服务器支持)

<script src="https://7n.w3cschool.cn/attachments/image/cimg/example.js"></script>

如果我们希望,根据页面本身的协议来决定加载协议,可以采用下面的写法

<script src="https://7n.w3cschool.cn/attachments/image/cimg/example.js"></script>

七.Javascript虚拟机

Js是解释型语言,不需要每次去编译,可以由解释器实时运行,方便运行和修改,刷新页面就可以重新解释;

缺点是每次运行都调用解释器,开销很大,运行速度慢于编译性语言,所以目前的浏览器都将js进行一定程度的编译生成类似字节码的中间代码,提高运行速度。

  • 早期浏览器内部对js的处理如下;

读取代码,进行语法分析,代码分解成词元---对词元进行语法分析,代码整理为语法树--翻译器,将代码转为字节码---字节码解释器,将字节码转为机器码

  • 现代浏览器:及时编译(JIT just in time compiler)字节码只在运行时编译,用到哪行编译哪行,把编译结果缓存;不同浏览器编译策略不同,有的只编译最常用的部分,比如循环,chrome v8引擎索性忽略字节码翻译步骤,直接编译成字节码。

字节码不能直接运行,而是运行在虚拟机上,把虚拟机也称为javascript引擎

Js运行未必全部基于字节码,也有源码,只有有可能,就通过JIT把源码便以为机器码,尽可能优化代码提高性能

常用虚拟机:

Chakra  ie

Nitro/javascript core safari

SpiderMonkey  firfox

v8 chrome

 

八.单线程:

Js是单线程的,event loop用来等待和发送消息,所有的任务分为同步任务和异步任务,同步任务指的是,在主线程排队执行的任务,执行完一个任务才能执行下一个任务;异步任务,指的是不进入主线程,而进入“任务队列”的任务,只有任务队列通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

 

以Ajax操作为例,它可以当作同步任务处理,也可以当作异步任务处理,由开发者决定。如果是同步任务,主线程就等着Ajax操作返回结果,再往下执行;如果是异步任务,该任务直接进入“任务队列”,主线程跳过Ajax操作,直接往下执行,等到Ajax操作有了结果,主线程再执行对应的回调函数。

 

上图的绿色部分是程序的运行时间,红色部分是等待时间。可以看到,由于I/O操作很慢,所以这个线程的大部分运行时间都在空等I/O操作的返回结果。这种运行方式称为"同步模式"(synchronous I/O)。

上图主线程的绿色部分,还是表示运行时间,而橙色部分表示空闲时间。每当遇到I/O的时候,主线程就让Event Loop线程去通知相应的I/O程序,然后接着往后运行,所以不存在红色的等待时间。等到I/O程序完成操作,Event Loop线程再把结果返回主线程。主线程就调用事先设定的回调函数,完成整个任务。

可以看到,由于多出了橙色的空闲时间,所以主线程得以运行更多的任务,这就提高了效率。这种运行方式称为"异步模式"(asynchronous I/O)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值