JavaScript学习笔记28
Posted -恰饭第一名-
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JavaScript学习笔记28相关的知识,希望对你有一定的参考价值。
一、json
- JSON是一种传输数据的格式(以对象为样板,本质上就是对象,但用途有区别,对象就是本地用的,json是用来传输的)
- JSON.parse(); string---->json
- JSON.stringify(); json---->string
例:json的属性名必须加双引号(传的是二进制文本)
<script>
var obj = {
"name": "abc",
"age": 123
}
var str = JSON.stringify(obj);
</script>
思路:绘制dom树,符合深度优先(纵向)原则,比如先看head—>title—>meta—>body—>div—>strong—>span
dom树是节点解析,dom树解析完毕代表dom树所有的节点解析完毕,不代表加载(下载完毕)完毕。如看到img标签就放到dom树上,然后同时下载
dom树形成完了以后,就等css树形成【cssTree也是深度优先原则】
domTree+cssTree=randerTree,randerTree形成以后。渲染引擎才会绘制页面
domTree改变,randerTree也会改变,会重排,影响效率,要尽量避免重排。
randerTree触发重排(reflow)的情况:dom节点的删除,添加,dom节点的宽高变化,位置变化,display none==>block,offsetWidth,offsetLeft
repaint 重绘:效率也比较低,效率影响较小。触发情况:改颜色,图片
二、异步加载js
js是单线程的,会阻断html,css加载(因为js会修改html和css,一起加载会乱)
所以是同步加载js,先下载js,再下载HTML和css。常规来说js是同步加载的,所以我们讲讲js异步加载的情况
1、 js加载的缺点:加载工具方法没必要阻塞文档,过度加载js会影响页面效率,一旦网速不好,那么整个网站将等待js加载而不进行后续渲染等工作
2、有些工具方法需要按需加载,用到再加载,不用时不加载
3、 javascript异步加载的三种方案
- defer异步加载,但要等到dom文档全部解析完(dom树生成完)才会被执行,只有IE能用,可以把js写在script标签里。
(dom文档全部解析完,不代表整个页面加载完) - async 异步加载,加载完就执行,async只能加载外部脚本,不能把js写在script标签里。ie9以上也可以用,w3c标准
(1和2执行时也不阻塞页面) - 创建script,插入到DOM中,加载完毕后callBack(按需加载,方便)—》常用
js异步加载,属性名和属性值相同可以只写一个defer=“defer”
下面这样也可以实现异步加载
async异步加载
创建script,插入到dom中,加载完毕后callBack
<script>
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "tools.js";
document.head.appendChild(script);
//如果不写这一段,就是只加载,不执行,像这样写了执行以后才执行
</script>
预加载机制:img的灯塔模式
demo.js
上面这种方式不能执行,会报错
思考:为什么上一个例子当前执行,执行不了,但是设置定时器以后就能执行了?
答案:因为还没有下载完。因为程序执行是非常快的,当程序读到document.head读到test()时上面的script.type和script.src还没又下载完,所以执行不了
所以,能不能有一个方法提示我们,他下载完了,等他下载完了我们在用?
方法一:非ie方法script.οnlοad=function(){},触发script.onload事件就代表他下载完了,当他们下载完了再执行test()
<script>
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "demo.js";
script.onload = function() {
test();
}
document.head.appendChild(script);
</script>
function test() {
console.log("a");
}
方法二:ie上有一个状态码,script.readyState,功能与script.onload相似
script.readyState=“loading”;最开始的值
script.readyState=“complete”;或者"leaded"表示加载完成
监听这个方法的事件
<script>
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "demo.js";
if (script.readyState) {
script.onreadystatechange = function() {
if (script.readyState == "complete" || script.readyState == "loaded") {
test();
}
}
} else {
script.onload = function() {
//Safari chrome firefox opera
test();
}
}
document.head.appendChild(script);
</script>
例:我们把以上两种异步加载js方法封装成函数:(左下是方法三的封装库)
<script>
function loadScript(url, callback) {
var script = document.createElement("script");
script.type = "text/javascript";
script.src = "demo.js";
if (script.readyState) {
script.onreadystatechange = function() {
if (script.readyState == "complete" || script.readyState == "loaded") {
callback();
}
}
} else {
script.onload = function() {
//Safari chrome firefox opera
callback();
}
}
script.src = url;
document.head.appendChild(script);
}
</script>
事件里面有一个绑定的事件处理函数,当满足一定执行条件才执行的函数叫做回调函数。回调函数叫callback
把上面那个函数折叠,加上下面
执行顺序 :先function loadScript(){}
【不会看里面的代码是什么】,再loadScript()【这一步的时候不知道test是什么】,然后执行function里面的内容
为了解决上面的问题,如下例:
利用callback变成字符串形式,(不让用eval,只做扩展)
下面是更好的方法,需要配合库实现
三、js 加载时间线(可以理解成浏览器加载时间线)
js 加载时间线:依据 js 出生的那一刻起,记录了一系列浏览器按照顺序做的事(就是一个执行顺序)
js 时间线步骤(创建 document 对象==>文档解析完==>文档解析完加载完执行完)
- 创建 Document 对象,开始解析 web 页面。解析 HTML 元素和他们的文本内容后添加 Element 对象和 Text 节点到文档中。这个阶段 document.readyState = ‘loading’。
- 遇到 link 外部 css,创建线程,进行异步加载,并继续解析文档。
- 遇到 script 外部 js,并且没有设置 async、defer,浏览器同步加载,并阻塞,等待 js 加载完成并执行该脚本,然后继续解析文档。
- 遇到 script 外部 js,并且设置有 async、defer,浏览器创建线程异步加载,并继续解析文档。
对于 async 属性的脚本,脚本加载完成后立即执行。(异步禁止使用 document.write(),因为当你整个文档解析到差不多,再调用 document.write(),会把之前所有的文档流都清空,用它里面的文档代替)
- 遇到 img 等(带有 src),先正常解析 dom 结构,然后浏览器异步加载 src,并继续解析文档。 看到标签直接生产 dom 树,不用等着 img 加载完 scr。
- 当文档解析完成(domTree 建立完毕,不是加载完毕),document.readyState = ‘interactive’。
- 文档解析完成后,所有设置有 defer 的脚本会按照顺序执行。(注意与 async 的不同,但同样禁止使用 document.write());
- document 对象触发 DOMContentLoaded 事件,这也标志着程序执行从同步脚本执行阶段,转化为事件驱动阶段。
- 当所有 async 的脚本加载完成并执行后、img 等加载完成后(页面所有的都执行加载完之后),document.readyState = ‘complete’,window 对象触发 load 事件。
- 从此,以异步响应方式处理用户输入、网络事件等。
异步禁止使用document.write()
用window.onload会等整个页面加载完才执行,消除文档流(把自己script删了)
执行到document.readyState时,整个dom树还没有解析完,所以不会是interactive
我们就利用window.onload事件,看到的是complete,代表执行加载完
如果想看到 interactive,所有事件都是用的小写
这个事件只在 addEventListener 上面能用
通用写法是把 JS 的 script 写在最下面,为什么我们要把他写在最下面?写在最下面意味着上面的 dom 已经处理完毕了。window.onload 是整个页面加载完才执行,慢 , dom 解析完毕就执行完就执行,比较快。
只要有一个图片没加载完,window.onload 就不能用,所以效率非常低下
script 标签这样写在上面。又能操作 div,又能 dom 解析完就处理,效率很高。但是最好还是写在最下面
四、BOM(权限过大,不让用)
定义:Browser Object Model,定义了操作浏览器的接口
BOM 对象: Window, History,Navigator,Screen, Location 等
由于浏览器厂商的不同,Bom 对象的兼容性极低。一般情况下,只用其中的部分功能。
Window
History 对象
Navigator 对象
http://www.w3school.com.cn/jsref/dom_obj_navigator.asp
Screen 对象
Location 对象
location.hash
“#”后是对浏览器操作的,对服务器无效,实际发出的请求也不包含”#”后面的
部分
“#”被算作历史记录
以上是关于JavaScript学习笔记28的主要内容,如果未能解决你的问题,请参考以下文章
ArcGIS API for JavaScript 4.2学习笔记[28] 可视域分析使用Geoprocessor类
译文:18个实用的JavaScript代码片段,助你快速处理日常编程任务
[原创]java WEB学习笔记61:Struts2学习之路--通用标签 property,uri,param,set,push,if-else,itertor,sort,date,a标签等(代码片段