前端--关于客户端javascript
- 浏览器中的Javascript
客户端javascript就是运行在浏览器中的javascript,现代的浏览器已经有了很好的发展,虽然它是一个应用程序,但完全可以把它看作是一个简易的操作系统,因为像windows、linux等操作系统提供的文档存储、网络调用、绘制图像等功能在浏览器中也同样都可以得到支持,所以就像操作系统中的应用程序叫做桌面应用一样,浏览器中可互动的web文档也叫做web应用。
在web应用中,浏览器是javascript的运行环境,这个运行环境不仅包含了javascript解释器以使js程序可以正确的运行,还为解释器提供了其他服务的接口来扩展了javascript的功能,比如发起网络调用、DOM编程等。当一个页面开始加载的时候js解释器就会启动,启动后做的第一件事就是初始化一个全局对象,这个全局对象在不同运行环境中会有不同的标识符表示和内容,在nodeJS中这个全局对象叫global,而在浏览器中这个全局对象叫window。一个window对象就代表一个窗体,里面除了包含javascript语法内置的函数和对象外,还包括浏览器为其扩展的功能对象,这些功能对象就是前面说的服务接口,是浏览器提供的服务的对象化表示。
- Javascript的执行
解释器启动之后就可以执行javascript代码了,在浏览器中触发javascript代码运行的情况只有两种:
- 文档加载的时候:浏览器在加载解析页面文档的过程中如果遇到了<script>标签引用或者包含的js代码,解释器就会执行一遍。
- 事件触发的时候:这种情况是异步且由事件驱动的,解释器执行的代码是前一种情况下为事件注册的处理函数。
其中第一种情况要尤其注意,当浏览器在下载和执行js文件的时候,页面的解析和渲染是被阻塞的,也就是说页面的其他有关资源会停止下载(比如css文件、图片等),同时DOM树的构建也会暂停,因为js程序的执行是有可能影响到DOM树的结构的(比如说使用到了document.write方法),DOM树的解析一暂停,页面的UI渲染也会被迫暂停。这样就会产生性能问题,如果js文件过大或者js代码执行时间过长,浏览器等待响应的时间就越久。所以考虑到性能问题,浏览器中js脚本应该尽可能的是无阻塞的脚本。
- 无阻塞脚本
由阻塞脚本的阻塞过程可以知道,无阻塞的脚本可以从两个方面来考虑:不阻塞页面相关资源的下载和不阻塞页面UI的渲染。
要是单单实现不阻塞其他资源的下载只有一种方法,就是在<script>标签中添加defer或者async,这种方法的效果是实现并行下载,也就是说当js文件在下载的时候不会阻塞其他资源的下载,它俩的区别是下载完后js代码执行的时机,defer会一直推迟到页面解析完,而async会在js文件下载完后立即执行,但js文件在执行过程中还是会阻塞页面解析和渲染的。由于浏览器对这种方法的支持不是很充分,所以这并不是一个兼容性很强的方法。
其他的几种方法就是既不阻塞下载也不阻塞渲染了,首先是一种讨巧的方法,就是把<script>标签放到<body>底部,因为浏览器是一边解析渲染一边显示出来的,等解析到body标签最底部的时候页面也就完全在浏览器中显示出来了,这时候再下载和执行js文件基本上不存在阻塞这回事情了,但是要注意的是放到最后面的js文件尽量不要再对DOM进行操作,因为更改了DOM可能会产生回流或者重绘,回流和重绘也是非常耗性能的两个操作,影响用户的使用体验。还有一点是asp.net程序要注意的是在webform编程中,如果后台代码要用到前台的js函数,那么放在body标签底部的函数是注册不过去的,后台只能注册放在head标签中的函数。
还有一种方法是创建动态脚本元素,这种方法可以说是做到了异步无阻塞,在js文件下载和执行的时候都不会阻塞页面的解析和渲染。该方法需要动态的创建script标签,并把标签添加到head元素中,比如
var script = document.createElement('script');
script.type='text/javascript';
script.src='xxxxx.js';
document.getElementsByTagName('head')[0].appendChild(script);
当代码执行到最后一句的时候js文件开始下载,下载完后立即执行,这整个过程不会阻塞页面解析和渲染。这是动态创建带有src属性的script标签的时候,还有另外一种动态创建内联脚本的方式,该方法通过Ajax请求获取到js脚本内容,再动态创建script标签把脚本内容注入到script标签当中。这种方法不是很常用因为有一个缺点就是获取的js内容只能是同域中的。
一个性能良好的页面不只是要做到无阻塞脚本,还有很多其他方面要注意的。 其中一条就是不要让一段js代码执行太长时间,因为javascript语言中不存在任何线程机制,并且js引擎也是单线程模型的,所以js代码的执行都是同步的,长时间的占用执行线程会使其他的js代码无法得到执行。如果必须要计算一个密集的任务,那么可以把这个任务通过setTimeout或setInterval分离成多个异步子任务。这里的同步和异步看起来似乎有些矛盾,javascript怎么可能既是单线程同步的又是多线程异步的呢? 原因在于浏览器的机制。
- Javascript单线程与事件的异步
虽然javascript引擎是单线程的,但是浏览器是多线程的,在一个浏览器进程中一般有四个线程:javascript引擎线程、渲染引擎线程、浏览器事件线程(我也不知道叫什么)、http请求线程。在javascript引擎线程中有一个执行队列,里面的任务是同步的依次执行,而在浏览器事件线程中有一个任务队列,当某个事件触发时,该事件对应的回掉函数会放到这个任务队列中,这个任务队列是一个先进先出结构,当javascript引擎线程中的任务都执行完毕后,会从浏览器事件线程中的任务队列里读取任务放到javascript引擎线程中的执行队列里去执行,这个过程是不断循环的,这有个专业术语叫Event Loop。所以就算setTimeout(fun,0)这种看起来是立即执行的函数也并不一定会立即执行的,这个fun函数会先放到任务队列里面等待执行队列中的任务执行完毕才会被执行,所以fun函数的执行会延迟一段时间,这么样子的写法只是改变了fun函数的执行顺序。
前端--关于客户端javascript的更多相关文章
- 前端html、Javascript、CSS技术小结
简单地总结了一下前端用过的html.javascript.css技术,算是清点一下,做个大略的小结,为进一步的学习给个纲领. 一.HTML 由于HTML5的兴起,简单地判断一个网页是否是html5网页 ...
- 前端基础之JavaScript day51
前端基础之JavaScript JavaScript概述 JavaScript的历史 1992年Nombas开发出C-minus-minus(C--)的嵌入式脚本语言(最初绑定在CEnvi软件中) ...
- 前端html+css+JavaScript 需要掌握的单词
前端html+css+JavaScript 需要掌握的单词 broswer 浏览器(客户端) html 超文本标记语言 css 层叠样式表 javascript 语言名字(类似python/php ...
- 前端第三篇---前端基础之JavaScript
前端第三篇---前端基础之JavaScript 一.JavaScript概述 二.JavaScript的基础 三.词法分析 四.JavaScript的内置对象和方法 五.BOM对象 六.DOM对象 七 ...
- 前端开发:Javascript中的数组,常用方法解析
前端开发:Javascript中的数组,常用方法解析 前言 Array是Javascript构成的一个重要的部分,它可以用来存储字符串.对象.函数.Number,它是非常强大的.因此深入了解Array ...
- 【JavaScript权威指南(第五版)】笔记之第二部分 客户端JavaScript 第13章~第23章
第十三章 Web浏览器中的javascript ① eg:下面两行代码实际上执行的是相同的功能 var answer = 42; window.answer = 42; ③每个window对象 ...
- JavaScript 客户端JavaScript之脚本化HTTP(通过XMLHttpRequest)
XMLHttpRequest对象的设计目的是为了处理由普通文本或XML组成的响应:但是,一个响应也可能是另外一种类型,如果用户代理(UA)支持这种内容类型的话. 大多数浏览的客户端JavaScri ...
- JavaScript 客户端JavaScript之事件(DOM API 提供模块之一)
具有交互性的JavaScript程序使用的是事件驱动的程序设计模型. 目前使用的有3种完全不同的不兼容的事件处理模型. 1.原始事件模型 (一种简单的事件处理模式) 一般把它看作0级DOM API ...
- JavaScript 客户端JavaScript之 Web浏览器的环境
Web浏览器实现的Javascript,通过Web浏览器实现的JavaScript引入了大量可脚本化的对象(1.Web浏览器 2.HTML 3.HTML中的内容) Web浏览器中的Javascrip ...
随机推荐
- CSS3滤镜filter浅析
在实现特定显示效果的页面中,css的filter属性是一种强大的工具.它能让我们的页面更加地个性化并减少PS方面的工作.filter的属性值主要有以下十种: blur grayscale sepia ...
- SqlBulkCopy使用心得 (大量数据导入)
文章转载原地址:http://www.cnblogs.com/mobydick/archive/2011/08/28/2155983.html 最近做的项目由于之前的设计人员懒省事,不按照范式来,将一 ...
- struts 标签引用出错
几句句话概括 1.检查 web.xml 出现错误自己改 配置后filter jsp-config 2.检查 tld 目录下的东西 是否缺少 3. 将包复制到web的lib目录下后 之后 b ...
- cocos2dx 碰撞检测
//必须 要有float类型的参数 void MainScene::updateFrame(float dt) { if (spriteTest != NULL && spriteTe ...
- C#计算当前日期为一年中的第几周
方法一: private int WeekOfYear(string date) { DateTime curDay = Convert.ToDateTime(date); i ...
- gitweb随记
1.安装gitweb,命令安装即可 apt-get install gitweb 2.clone cgi $ git clone git://git.kernel.org/pub/scm/git/gi ...
- 永久存储:腌制一缸美味的泡菜 - 零基础入门学习Python031
永久存储:腌制一缸美味的泡菜 让编程改变世界 Change the world by program 从一个文件里读取字符串非常简单,但如果想要读取出数值,那就需要多费点儿周折.因为无论是read() ...
- U盘启动时无USB-HDD选项的解决方案
今天在使用一块老板子的时候 发现没有USB-HDD启动项 在启动顺序中只有 USB-ZIP(ZIP) -FDD(软盘) -CDROM(光驱) 1.插入U盘 2.开机 3.在BIOS中找到Hard D ...
- 使用 JUnit 进行单元测试 - 教程
tanyuanji@126.com 版本历史 JUnit 该教程主要讲解 JUnit 4.x 版本的使用,以及如何在Eclipse IDE 中如何使用JUnit 目录 tanyuanji@126. ...
- Sql server中Collation conflict问题
SQL语句查询时select A.Code,A.Name,a.Systemcode,B.ID,B.LogType,B.DMCode,B.IP,B.Department,B.CreateBy,B.Cre ...