《JavaScript权威指南》阅读笔记(下)
Apr 3, 2016
继续阅读,这里是客户端JavaScript实现的部分

Web浏览器中的JavaScript
Location对象的新发现
123location == location.href // true,location 对象调用了 toString() 方法location = 'www.example.com' // 相当于给 location.href 赋值window.location === document.location // true<script>标签如果有src属性,则<script>标签中的任何内容均会被忽略<script>标签中如果包含不被浏览器识别的type属性,浏览器会尝试解析但不执行/显示,利用这个可以做成HTML模板(只限内联),如<script type="yhsd-template">...模板内容...</script>;但如果同时又指定了src属性,该标签会被忽略
window对象
setTimeout(func, 0)中,函数func不会立刻执行,而是等待前面事件处理程序都运行完再“立即”执行- 一个有趣的历史遗留问题是,当元素的
id(或特殊元素的name)不是window对象的一个属性时,该元素会被隐式的成为全局的一个属性。实践中尽量避免使用这种方式,HTML5 标准中已废弃123456789101112131415<button id="btn">我会被隐式成为全局属性</button><button id="alert">我被alert方法覆盖了!!!</button><button id="user">我被自定义全局变量方法覆盖了!!!</button><br><img class="foo" name="foo" src="example2.png"><img class="foo" name="foo" src="example3.png"><script>window.btn === document.getElementById('btn') // truewindow.alert === document.getElementById('alert') // false,被 window.alert 方法覆盖//var user = 'user defined'window.user === document.getElementById('user') // false,被自定义全局变量覆盖了//window.foo === document.getElementsByClassName('foo') // false 前者为 HTMLCollection 对象,后者为NodeList对象</script>
脚本化文档
- HTMLCollection 和 NodeList 对象是动态的,实时反应 DOM 中的变化,因此在实际应用中可能需要保存获取时的静态副本以避免后续变动造成影响
- HTMLCollection 和 NodeList 对象具有细微的区别,前者是标准DOM的 Core 接口,后者为 HTML 独有并多了一个
namedItem方法;HTMLCollection 是元素集合而 NodeList 是节点集合(即可以包含元素,也可以包含文本节点) - 标准显示的文档中,
getElementsByClassName()方法区分大小写(怪异模式则不区分大小写) - IE8不支持
getElementsByClassName()方法,但却支持querySelectorAll()方法 通过
querySelectorAll()获取的 NodeList 对象不是实时动态的,而是获取时的静止快照。querySelector()只选中第一个匹配的元素。在Element调用 querySelector 方法,选择器仍然搜索整个文档,但会过滤出基于该 Element 的后代元素返回,这意味着在这种情况下相对于
getElementBy*方法会消耗更多的性能对于
<p>This is a <i>simple</i>document</p>而言,<p>标签中的内容是什么?innerHTML——This is a <i>simple</i>documentouterHTML——<p>This is a <i>simple</i>document</p>innerText——This is a simple document
- 元素、滚动条、窗口的大小位置获取及设置的理解(结合图示)
onsubmit事件处理程序中返回false可取消提交,该事件只能通过“提交”按钮触发,直接用JS调用submit()方法无效(onreset同理)- 建议不用
<a>标签模拟非链接的按钮,以更加语义化(当脚本失效时用链接代替按钮的功能是一种优雅降级,脚本失效仍可点开新页面进入下一步) - 单选/复选按钮中使用
change事件代替click <input type="file">的value是只读的,防止恶意JS上传- 通过设置标签的
contenteditable属性创建可编辑区域是富文本编辑器的常用手段,其中浏览器支持多种 API,但这些 API 的兼容可能需要考虑,建议使用富文本编辑器插件。
脚本化CSS
- 元素的style属性的值是一个
CSSStyleDeclaration对象,而非字符串,而其所有属性的值都是字符串(必须带单位,如’20px’);该对象读取和改变的均是 HTML/JS 显示声明的内联样式,因此外联样式表的样式无法被读取。 - 计算样式也是得到一个
CSSStyleDeclaration对象,使用window.getComputedStyle(element, null)- 计算样式是只读的
- 其属性的值是绝对值,相对值会转化成绝对值
- 不计算 margin 这种复合属性,而是 marginLeft 这种基础属性
- 未定义 cssText 属性
- 不支持 IE8 及以下版本(IE 中类似的方法为 currentStyle)
- 通过
document.styleSheets可获得只读的样式列表,包括内联和外联样式
事件处理
focus和blur事件不会冒泡- 如使用
beforeunload事件可以询问用户是否离开当前页面 addEventListener()方法的第三个参数通常省略(省略false即为冒泡模式),相同参数只能注册一次- IE8使用
attachEvent(),只支持事件冒泡(因此没有第三个参数),带on前缀,可多次注册多次调用 通过设置属性注册
IE8的事件对象时通过window.event传递而非标准的参数1234e.onclick = function (event) {event = event || window.event; // IE8中通过window.event传递event}// 而在attachEvent则两种方式均可事件处理程序的运行环境如下
123456789101112// 通过设置属性注册,会被转换为能存取全局变量的顶级函数,但由于历史原因,也能使用局部变量e.onclick = function (event) {this === event // true, this 指向事件目标}// 通过事件添加器注册e.addEventListener('click', function (event) {this === event // true, this 指向事件目标}, false)//e.attachEvent('click', function (event) {this === event // false, this 指向全局对象 window})尽量避免使用 HTML 属性来绑定事件处理程序,因为其隐式改过的作用域会导致许多问题
- 通过 HTML 属性绑定的事件处理程序返回
false可阻止其默认行为,而通过addEventListener()或attachEvent()方式则可通过调用preventDefault()或者设置其returnValue属性实现 - 多个事件处理程序作用于同一个事件时,通过 HTML 属性绑定的事件处理程会优先调用(类似内联样式),
addEventListener()则按注册顺序调用 - 文档元素的
load事件会冒泡到document对象并停止(不会冒泡到window对象),只有整个文档都加载完毕才会出发window的load事件 - 事件传播的三个阶段:事件捕获,目标事件处理程序,事件冒泡(DOM Lv3中标准化)
addEventListener()调用stopPropagation(),或attachEvent()设置cancelBubble属性为true,均可阻止事件的传播(阻止冒泡)- window 对象的
load事件触发需要文档和全部图片等资源加载完毕后才触发,而DOMContentLoaded事件则在 DOM 结构解析完毕且延迟脚本执行完毕即触发(在具备很多图片和异步脚本时比load事件更快完成,类似 jQuery 的$(document).ready()方法) - 除了
mouseenter和mouseleave外的鼠标事件均会冒泡
脚本化HTTP
- 常见的实现(均基于GET):
- 方法1:设置一个
<img>元素的src属性,把信息(如当前地址)作为图片 URL 的查询字符串部分,服务器会返回一个信标图片作为请求结果(通常是1×1像素的透明图片),该方法是单向的,但不受同源限制,一般用来跟踪流量 - 方法2:使用
<iframe>(通常对用户也不可见)代替<img>,服务器返回是包含响应内容的 HTML 在iframe中显示,脚本再遍历得到目的信息,该方法受限于同源策略 - 方法2:设置
<script>作为容器,该方法兼具方法1和方法2的优点(双向交互,不受同源限制),常见主流实现如JSONP
- 方法1:设置一个
- GET 请求适用于
URL完全制定请求资源,对服务器无任何副作用,且其响应可缓存的情况 xhr.open('GET', url, false),第三个参数显示传入false,则该请求为同步阻塞的,一般避免使用
客户端存储
localStorage和sessionStorage均代表同一个 Storage 对象(一个持久化关联数组),数组的使用字符串索引和字符串形式的值;两者的区别在于存储时间及访问权限localStorage的存储期限是永久的(除非刻意删除),而sessionStorage则在标签(会话级别)关闭后即失效localStorage可被同源文档读写(不同标签页间共享),而sessionStorage不禁限制同源还限制不同标签页不能共享
- 当
Storage数据发生改变时会触发存储事件(onstorage) - IE8 以上版本支持 Storage,而 IE6/IE7 可用类似的
userData实现 - 同源一般说明:协议、主机名、端口均相同
- 要判断浏览器的
cookie是否启用的兼容方法是快速写入 / 读取测试数据 cookie的可读性与创建它的页面有关,当前页面同目录及其子目录可见,而对其他页面不可见(可通过设置参数设置其目录路径)cookie在大部分浏览器中有大小限制,单个cookie限制为 4kb离线存储前需要设置
manifest(MIME类型:text/cache-manifest)清单:123456<html manifest="myapp.appcache">...</html><!-- 以下是上述清单文档的内容,更新版本号可让浏览器重新获取新资源以替换过时缓存 --># Myapp version 1myapp.htmlmyapp.cssmyapp.pngnavigator.onLine属性可以判断当前应用是否在线
多媒体和图形编程
SVG是一种描述图形的 XML 语法,IE9 及以上浏览器支持;- IE9 及以上浏览器支持
<canvas>
HTML5 API
- 地理位置 API 通常会弹窗提示用户授权使用位置信息
- 利用
location.hash和对应的hashchange事件可以实现IE8中的单页应用历史管理 - 利用GTML5新增的
history.pushState、history.replaceState及对应事件,可灵活管理 SPA 的历史状态 - IE8 支持
window.postMessage()方法进行窗口间信息传递