《JavaScript高级程序设计》读书笔记
window 对象
- ECMAScript 中的Global 对象
- 浏览器窗口的 JavaScript 接口
Global 作用域
window 对象被复用为ECMAScript 的Global 对象,所以通过var 声明的所有全局变量和函数都会成为window 对象的属性和方法。
窗口关系
- window.top 始终指向最上层(最外层)窗口,即浏览器窗口本身
- window.self 返回指向当前 window 对象的引用,利用这个属性,可以保证在多个窗口被打开的情况下,正确调用当前窗口内的函数或属性而不会发生混乱
- window.parent 指向当前窗口的父窗口
窗口位置
- window.screenLeft 表示窗口相对于屏幕左侧的位置
- windwo.screenTop 表示窗口相对于屏幕顶部的位置
- window.moveTo(x, y) 接收要移动到的新位置的绝对坐标 x 和 y
- windwo.moveBy(x, y) 接收相对当前位置在两个方向上移动的像素数
像素比
CSS 像素是 Web 开发中使用的统一像素单位。这个单位的背后其实是一个角度: 0.0213°。
同像素密度的屏幕下就会有不同的缩放系数,以便把物理像素(屏幕实际的分辨率)转换为 CSS 像素(浏览器报告的虚拟分辨率)。
window.devicePixelRatio 与每英寸像素数( DPI, dots per inch)是对应的。 DPI 表示单
位像素密度,而 window.devicePixelRatio 表示物理像素与逻辑像素之间的缩放系数。
窗口大小
返回浏览器窗口自身的大小
- window.outerWidth
- window.outerHeight
返回浏览器窗口中页面视口的大小(不包含浏览器边框和工具栏)
- window.innerWidth
- window.innerHeight
返回页面视口的宽度和高度
- document.documentElement.clientWidth
- document.documentElement.clientHeight
调整窗口大小
- window.resizeTo()
- window.resizeBy()
let pageWidth = window.innerWidth, pageHeight = window.innerHeight;
if (typeof pageWidth != "number") {
if (document.compatMode == "CSS1Compat"){
pageWidth = document.documentElement.clientWidth;
pageHeight = document.documentElement.clientHeight;
} else {
pageWidth = document.body.clientWidth;
pageHeight = document.body.clientHeight;
}
}
视口位置
度量文档相对于视口滚动距离的属性
- window.pageXoffset / windwo.scrollX
- window.pageYoffset / windwo.scrollY
文档滚动到指定坐标(接收表示相对视口距离的 x 和 y 坐标,也接收一个ScrollToOptions 字典)
- window.scroll() / window.scrollTo()
- window.scrollBy() 相对于当前视口滚动
// 滚动到页面左上角
window.scrollTo(0, 0)
// 相对于当前视口向下滚动100像素
window.scrollBy(0, 100)
// 平滑滚动
window.scrollTo({
left: 0,
top: 100,
behavior: 'smooth'
});
导航与打开新窗口
window.open():接收 4个参数:要加载的 URL、目标窗口、特性字符串和表示新窗口在浏览器历史记录中是否替代当前加载页面的布尔值。
如果 window.open()的第二个参数是一个已经存在的窗口或窗格( frame)的名字,则会在对应的
窗口或窗格中打开 URL。
// 与<a href="http://www.baidu.com" target="topFrame"/>相同
window.open("http://www.baidu.com/", "topFrame");
特性字符串:
设置 | 值 | 说明 |
---|---|---|
fullscreen | "yes"或"no" | 表示新窗口是否最大化。仅限 IE 支持 |
height | 数值 | 新窗口高度。这个值不能小于 100 |
left | 数值 | 新窗口的 x 轴坐标。这个值不能是负值 |
location | "yes"或"no" | 表示是否显示地址栏。不同浏览器的默认值也不一样。在设置为"no"时,地址栏 可能隐藏或禁用(取决于浏览器) |
Menubar | "yes"或"no" | 表示是否显示菜单栏。默认为"no" |
resizable | "yes"或"no" | 表示是否可以拖动改变新窗口大小。默认为"no" |
scrollbars | "yes"或"no" | 表示是否可以在内容过长时滚动。默认为"no" |
status | "yes"或"no" | 表示是否显示状态栏。不同浏览器的默认值也不一样 |
toolbar | "yes"或"no" | 表示是否显示工具栏。默认为"no" |
top | 数值 | 新窗口的 y 轴坐标。这个值不能是负值 |
width | 数值 | 新窗口的宽度。这个值不能小于 100 |
window.open()方法返回一个对新建窗口的引用。这个对象与普通 window 对象没有区别,只是为
控制新窗口提供了方便。例如,某些浏览器默认不允许缩放或移动主窗口,但可能允许缩放或移动通过window.open()创建的窗口。跟使用任何 window 对象一样,可以使用这个对象操纵新打开的窗口。
let page = window.open("http://www.baidu.com/", "wroxWindow","height=400,width=400,top=10,left=10,resizable=yes");
// 缩放
page.resizeTo(500, 500);
// 移动
page.moveTo(100, 100);
// 指向打开它的窗口
page.opener === window
// 关闭打开的窗口
page.close()
如果浏览器内置的弹窗屏蔽程序阻止了弹窗,那么 window.open()很可能会返回 null 或报错。
let blocked = false;
try {
let wroxWin = window.open("http://www.baidu.com", "_blank");
if (wroxWin == null){
blocked = true;
}
} catch (ex){
blocked = true;
}
if (blocked){
alert("The popup was blocked!");
}
定时器
setTimeout() 用于指定在一定时间后执行某些代码
JavaScript 维护了一个任务队列。其中的任务会按照添加到队列的先后顺序执行。如果队列是空的,则会立即执行该代码。如果队列不是空的,则代码必须等待前面的任务执行完才能执行。
clearTimeout() 取消任务
setInterval() 用于指定每隔一段时间执行某些代码
clearInterval() 取消任务
系统对话框
- alert() 警告框
- confirm() 确认框
- prompt() 提示框
- window.print() 打印对话框
- window.find() 查找对话框
location 对象
提供了当前窗口中加载文档的信息,以及通常的导航功能。它既是 window 的属性,也是document 的属性 。也就是说,window.location 和 document.location 指向同一个对象。
属性 | 说明 |
---|---|
location.hash | URL 散列值(井号后跟零或多个字符),如果没有则为空字符串 |
location.host | 服务器名及端口号 |
location.hostname | 服务器名 |
location.href | 当前加载页面的完整 URL。location 的 toString()方法返回这个值 |
location.pathname | URL 中的路径和(或)文件名 |
location.port | 请求的端口。如果 URL 中没有端口,则返回空字符串 |
location.protocol | 页面使用的协议。通常是"http:"或"https:" |
location.search | URL 的查询字符串。这个字符串以问号开头 |
location.username | 域名前指定的用户名 |
location.password | 域名前指定的密码 |
location.origin | URL 的源地址。只读 |
查询字符串
let getQueryStringArgs = function() {
// 取得没有开头问号的查询字符串
let qs = (location.search.length > 0 ? location.search.substring(1) : ""),
// 保存数据的对象
args = {};
// 把每个参数添加到 args 对象
for (let item of qs.split("&").map(kv => kv.split("="))) {
let name = decodeURIComponent(item[0]),
value = decodeURIComponent(item[1]);
if (name.length) {
args[name] = value;
}
}
return args;
}
URLSearchParams
接口定义了一些实用的方法来处理 URL 的查询字符串。可以直接用在 for...of 结构中
var paramsString = "q=URLUtils.searchParams&topic=api"
var searchParams = new URLSearchParams(paramsString);
for (let p of searchParams) {
console.log(p);
}
searchParams.has("topic") === true; // true
searchParams.get("topic") === "api"; // true
searchParams.getAll("topic"); // ["api"]
searchParams.get("foo") === null; // true
searchParams.append("topic", "webdev");
searchParams.toString(); // "q=URLUtils.searchParams&topic=api&topic=webdev"
searchParams.set("topic", "More webdev");
searchParams.toString(); // "q=URLUtils.searchParams&topic=More+webdev"
searchParams.delete("topic");
searchParams.toString(); // "q=URLUtils.searchParams"
操作地址
除了 hash 之外,只要修改 location 对象的属性就会修改当前加载的页面。
location.assign("http://www.baidu.com");
window.location = "http://www.baidu.com";
location.href = "http://www.baidu.com";
location.replace("http://www.baidu.com/"); // 不会增加历史记录
location.hash = "#section1";
location.search = "?q=javascript";
location.reload(); // 重新加载,可能是从缓存加载
location.reload(true); // 重新加载,从服务器加载
navigator 对象
存储了与浏览器相关的基本信息。
属性/ 方法 | 说明 |
---|---|
activeVrDisplays | 返回数组,包含 ispresenting 属性为 true 的 VRDisplay 实例 |
appCodeName | 即使在非 Mozilla 浏览器中也会返回"Mozilla" |
appName | 浏览器全名 |
appVersion | 浏览器版本。通常与实际的浏览器版本不一致 |
battery | 返回暴露 Battery Status API 的 BatteryManager 对象 |
buildId | 浏览器的构建编号 |
connection | 返回暴露 Network Information API 的 NetworkInformation 对象 |
cookieEnabled | 返回布尔值,表示是否启用了 cookie |
credentials | 返回暴露 Credentials Management API 的 CredentialsContainer 对象 |
deviceMemory | 返回单位为 GB 的设备内存容量 |
doNotTrack | 返回用户的“不跟踪”( do-not-track)设置 |
geolocation | 返回暴露 Geolocation API 的 Geolocation 对象 |
getVRDisplays() | 返回数组,包含可用的每个 VRDisplay 实例 |
getUserMedia() | 返回与可用媒体设备硬件关联的流 |
hardwareConcurrency | 返回设备的处理器核心数量 |
javaEnabled | 返回布尔值,表示浏览器是否启用了 Java |
language | 返回浏览器的主语言 |
languages | 返回浏览器偏好的语言数组 |
locks | 返回暴露 Web Locks API 的 LockManager 对象 |
mediaCapabilities | 返回暴露 Media Capabilities API 的 MediaCapabilities 对象 |
mediaDevices | 返回可用的媒体设备 |
maxTouchPoints | 返回设备触摸屏支持的最大触点数 |
mimeTypes | 返回浏览器中注册的 MIME 类型数组 |
onLine | 返回布尔值,表示浏览器是否联网 |
oscpu | 返回浏览器运行设备的操作系统和(或) CPU |
permissions | 返回暴露 Permissions API 的 Permissions 对象 |
platform | 返回浏览器运行的系统平台 |
plugins | 返回浏览器安装的插件数组。在 IE 中,这个数组包含页面中所有<embed>元素 |
product | 返回产品名称(通常是"Gecko") |
productSub | 返回产品的额外信息(通常是 Gecko 的版本) |
registerProtocolHandler() | 将一个网站注册为特定协议的处理程序 |
requestMediaKeySystemAccess() | 返回一个期约,解决为 MediaKeySystemAccess 对象 |
sendBeacon() | 异步传输一些小数据 |
serviceWorker | 返回用来与 ServiceWorker 实例交互的 ServiceWorkerContainer |
share() | 返回当前平台的原生共享机制 |
storage | 返回暴露 Storage API 的 StorageManager 对象 |
userAgent | 返回浏览器的用户代理字符串 |
vendor | 返回浏览器的厂商名称 |
vendorSub | 返回浏览器厂商的更多信息 |
vibrate() | 触发设备振动 |
webdriver | 返回浏览器当前是否被自动化程序控制 |
检查插件
除 IE10 及更低版本外的浏览器,都可以通过 plugins 数组来确定:
- name:插件名称
- description:插件介绍
- filename:插件的文件名
- length:当前插件处理的MiME 类型的数量
注意 plugins 有一个 refresh()方法,用于刷新 plugins 属性以反映新安装的插件。
这个方法接收一个布尔值参数,表示刷新时是否重新加载页面。如果传入 true,则所有
包含插件的页面都会重新加载。否则,只有 plugins 会更新,但页面不会重新加载。
// 插件检测, IE10 及更低版本无效
let hasPlugin = function(name) {
name = name.toLowerCase();
for (let plugin of window.navigator.plugins){
if (plugin.name.toLowerCase().indexOf(name) > -1){
return true;
}
}
return false;
}
// 检测 Flash
alert(hasPlugin("Flash"));
screen 对象
客户端能力信息
属性 | 说明 |
---|---|
availHeight | 屏幕像素高度减去系统组件高度(只读) |
availLeft | 没有被系统组件占用的屏幕的最左侧像素 |
availTop | 没有被系统组件占用的屏幕的最顶端像素 |
availWidth | 屏幕像素宽度减去系统组件宽度(只读) |
colorDepth | 表示屏幕颜色的位数;多数系统是 32(只读) |
height | 屏幕像素高度 |
left | 当前屏幕左边的像素距离 |
pixelDepth | 屏幕的位深(只读) |
top | 当前屏幕顶端的像素距离 |
width | 屏幕像素宽度 |
orientation | 返回 Screen Orientation API 中屏幕的朝向 |
history 对象
表示当前窗口首次使用以来用户的导航历史记录
导航
// 后退一页
history.go(-1);
// 前进一页
history.go(1);
// 前进两页
history.go(2);
// 后退一页
history.back();
// 前进一页
history.forward();
// 历史记录的数量
console.log(history.length);
历史状态管理
状态管理API 则可以让开发者改变浏览器 URL 而不会加载新页面。
- history.pushState() 新建历史记录
- history.replaceState() 更新状态不会创建新历史记录,只会覆盖当前状态
- onpopstate 每当活动的历史记录项发生变化时触发
let stateObject = {foo:"bar"};
history.pushState(stateObject, "My title", "baz.html")
window.addEventListener("popstate", (event) => {
let state = event.state;
if (state) { // 第一个页面加载时状态是 null
console.log(state);
}
});