《JavaScript高等程序设计》(第3版)读书笔记 第8章 BOM

  • ECMAScript是JavaScript的中心,但假如要在Web中运用JavaScript,那末BOM(阅读器对象模子)则无疑才是真正的中心。
  • W3C为了把阅读器中JavaScript最基础的部份标准化,已将BOM的重要方面纳入了HTML5范例中

window对象

  • BOM 的中心对是window,它示意阅读器的一个实例。在阅读器中window对象既是经由过程JavaScript接见阅读器窗口的一个接口,又是ECMAScript划定的Global对象,因而有权接见parseInt()等要领

全局作用域

  • 一切在全局作用域中声明的变量、函数都邑变成window对象的属性和要领。
  • 定义全局变量与直接在window对象上定义属性照样有一点差异:全局变量不能经由过程delete操纵符删除,而直接定义在window对象上的属性能够
var age = 29;
window.color = "red";

// 在IE < 9 时抛出毛病,在其他阅读器里返回 false
delete window.age;

// 在IE < 9 时抛出毛病,在其他阅读器里返回 true
delete window.color;

console.log(window.age);       // 29
console.log(window.color);     // undefined
  • 全局环境下运用var语句增加的window属性有一个名为[[Configruable]]的特征,这个特征的值被设置为false,因而不可经由过程delete删除。IE8及更早版本在碰到运用delete删除window属性的语句时,不论该属性最初怎样建立的,都邑抛出毛病,以示正告。
  • 尝试接见未声明的属性会抛出毛病,然则经由过程查询window对象,能够晓得某个能够未声明的变量是不是存在
// 这里会抛出毛病 oldValue 未定义
var newValue = oldValue;

// 这里不会抛出毛病,因为这是一次属性查询
// newValue的值是 undefined
var newValue = window.oldValue;

窗口关联及框架

  • 假如页面中包含框架,则每一个框架都具有自身的window对象,而且保存在frames鸠合中。
  • frames鸠合中,能够经由过程数值索引(从0最先,从左至右,从上到下)或许框架称号来接见响应的window对象。每一个window对象都有一个name属性,个中包含框架的称号。
<html>
  <head>
    <title> Frameset Example</title>
  </head>
  <frameset rows="160, *">
    <frame src="frame.htm" name="topFrame">
    <frameset cols="50%, 50%">
      <frame src="anotherframe.htm" name="leftFrame">
      <frame src="yetanotherframe.htm" name="rightFrame">
    </frameset>
  </frameset>
</html>
  • 能够经由过程window.frames[0]或许window.frames["topFrame"]来援用上方的框架,不过最好运用top而非window。比方 top.frames[0]
  • top对象一直指向最高(最外层)的框架,也就是阅读器窗口。
  • top相对的另一个window对象是parentparent(父)对象一直指向当前框架的直接上层框架。在某些状况下parent有能够即是top,但在没有框架的状况下,parent肯定即是top。此时他们都是window

窗口位置

  • 用来肯定和修正window对象位置的属性和要领有许多。

    • IE, Safari, Opera, Chrome 都供应了screenLeftscreenTop属性,离别用于示意相对屏幕左侧和上边的位置。
    • Firefox 则在 screenXscreenY 属性中供应雷同的窗口位置信息, Safari, Chrome也同时支撑这两个属性。
    • Opera虽然支撑 screenXscreenY 属性,但与 screenLeftscreenTop 并不对应,因而发起人人不要在 Opera中运用。
  • 运用以下代码能够跨阅读器获得窗口左侧和上边的位置
// 肯定 screenLeft 和 screenTop 属性是不是存在
// 存在,是在 IE, Safari, Opera, Chrome
// 不然,是在 Firefox中
var leftPos = (typeof window.screenLeft == "number") ?
                window.screenLeft : window.screenX;
var topPos = (typeof window.screenTop == "number") ?
                window.screenTop : window.screenY;
  • 在IE Opera 中,返回的是页面到屏幕边沿的间隔(不包含阅读器的工具栏等),而 Chrome Firefox Safari 返回的是阅读器到屏幕边沿的间隔(包含阅读器的工具栏等)。
  • 更让人抓狂的是, Firefox Safari Chrome 一直返回页面中每一个框架的 top.screenX top.screenY 值。纵然在页面因为被设置了外边距发作偏移的状况下,相关于window对象运用top.screenX top.screenY每次也都邑返回雷同的值。而IE Opera则会给出框架相关于屏幕辩护的准确坐标值。
  • 终究效果是没法在跨阅读器的条件下获得窗口左侧和上边的准确坐标值。
  • 运用moveTo()moveBy()要领,却是有能够将窗口的准确地挪动到一个新位置。这两个要领都吸收两个参数
// 将窗口挪动到屏幕左上角
window.moveTo(0, 0);

// 将窗口向下挪动100像素
window.moveBy(0, 100);

// 将窗口挪动到(200, 300)
window.moveTo(200, 300);

// 将窗口向左挪动50像素
window.moveBy(-50, 0);
  • 须要注重的是,这两个要领能够会被阅读器禁用;而且在Opera和IE7+中默许就是禁用的。
  • 这两个要领都不适用于框架,只能对最外层的window对象运用。

窗口大小

  • 跨阅读器肯定一个窗口的大小不是一件简朴的事变。

    • IE9+ Firefox Safari Opera Chrome 均为此供应了4个属性:innerwidth innerHeight outerWidth outerHeight
    • IE9 Safari Firefox 中 outerWidth outerHeight 返回阅读器窗口自身的尺寸(无论是从最外层的window对象照样从某个框架接见)。
    • Opera中这两个属性的值示意页面视图容器的大小。
    • innerwidth innerHeight则示意容器中页面视图区的大小(减去边框宽度)。
    • Chrome 中 四个值返回的雷同,即视口(viewport)大小而非阅读器窗口大小。
  • 下面的代码能够跨阅读器获得视口大小,但终究没法肯定阅读器窗口自身大小
var pageWidth = window.innerWidth;
var pageHeight = window.innerHeight;

// document.compatMode 这个属性将在第10章议论
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;
  }
}
  • 运用 resizeTo()resizeBy() 要领能够调解阅读器窗口的大小。须要注重,这两个要领也能够被阅读器禁用。在Opera和IE7+中默许制止
  • 这两个要领不适用于框架,只能对最外层的window对象运用
// 调解到 100 x 100
window.resizeTo(100, 100);

// 调解到 200 x 150
window.resizeBy(100, 50);

// 调解到 300 x 300
window.resizeTo(300, 300);

导航和翻开窗口

  • window.open() 要领既能够导航到一个特定的URL,也能够翻开一个新的阅读器窗口。吸收四个参数:

    • 要加载的URL
    • 窗口目标 (窗口或许框架的名字以及特别窗口称号: _self, _parent, _top, _blank)
    • 特征字符串(新窗口的特征设置,逗号分开)
    • 示意新页面是不是庖代阅读器历史纪录中当前加载页面的布尔值
// 等同于 <a href="http://www.wrox.com" target="topFrame"></a>
window.open("http://www.wrox.com", "topFrame");
弹出窗口
  • 假如给window.open()通报的第二个参数并非一个已存在的窗口或许框架,那末该要领就会依据在第三个参数位置上传入的字符串建立一个新窗口或许新标签。
  • 假如没有传入第三个参数,那末就会翻开一个带有悉数默许设置(工具栏、地点栏和状态栏等)的新阅读器窗口(或许新标签)。
  • 在不翻开新窗口的状况下,会疏忽第三个参数。
  • 第三个参数是一个逗号分开的设置字符串,示意新窗口有哪些特征。
设置申明
fullscreenyes/no示意阅读器窗口是不是最大化。仅限IE
height数值示意新窗口的高度。不能小于100
width数值示意新窗口的宽度。不能小于100
left数值左坐标,不能是负值
top数值上坐标。不能是负值
locationyes/no示意是不是在阅读器窗口中显现地点栏。差别阅读器的默许值差别。假如设置为no,地点栏能够会隐蔽,也能够会禁用,取决于阅读器
menubaryes/no是不是显现菜单栏。默许no
resizeableyes/no是能够拖动窗口大小。默许值no
scrollbarsyes/no是不是许可转动。默许no
statusyes/no是不是显现状态栏。默许no
toolbaryes/no是不是显现工具栏。默许no
  • window.open()要领会返回一个指向新窗口的援用,大抵与其他window对象一致,但我们能够举行更多操纵掌握。

    • 比方有些阅读器针对经由过程window.open()建立的还口不许可我们针对朱阅读器窗口调解大小或挪动位置,但却许可我们针对经由过程window.open()建立的窗口调解大小或挪动位置。
var wroxWin = window.open("http://www.wrox.com", "wroxWindow",
            "height=400,width=400,top=10,left=10,resizable=yes");

// 新建立的window对象有一个opener属性
// 保存翻开它的原始窗口对象
// 而原始窗口不跟踪翻开的新窗口,没有指向新窗口对象的属性
console.log(wroxWin.opener == window); // true

// 调解大小
wroxWin.resizeTo(500, 500);

// 挪动位置
wroxWin.moveTo(100, 100);

// 封闭新翻开的窗口
// 这个要领仅限于经由过程 window.open() 翻开的弹出窗口
// 关于主窗口假如没有获得用于的许可是不能封闭它的。
wroxWin.close();

// 弹窗封闭后,窗口的援用依然还在
// 但除了检测其closed属性没有其他用途
console.log(wroxWin.closed);    // true
  • 有些阅读器(如IE8 和 Chrome)会在自力的进程运转每一个标签页。当一个标签翻开另一个标签页时,假如两个window对象之间须要相互通讯,那末新标签就不能运转在自力的进程中。
  • 在Chrome中新建的标签页opener属性设置为null,即示意在零丁的进程中运转新标签
var wroxWin = window.open("http://www.wrox.com", "wroxWindow",
            "height=400,width=400,top=10,left=10,resizable=yes");

wroxWin.opener = null;
平安限定
  • 现在大部份阅读器都不能经由过程第四个参数修正是不是显现状态栏,不许可弹窗到屏幕不测,不许可封闭地点等等,增强弹窗的平安性,以避免用户和体系对话框殽杂。
  • Chrome采取了差别的处置惩罚体式格局,它不会像其他阅读器那样简朴的屏障这些弹窗,而是只是显现它们的标题栏,并放在窗口右下角。
弹出窗口屏障递次
  • 大部份阅读器或许阅读器插件都邑屏障弹窗,此时window.open()极能够返回null。此时只需搜检这个返回值就能够肯定弹窗是不是被屏障。
var wroxWin = window.open("http://www.wrox.com", "_blank");
if (wroxWin == null) {
  console.log("The popup was blocked!");
}
  • 阅读器拓展递次(插件)或其他递次阻挠弹窗,那末 window.open()平常会抛出毛病。因而不但要检测返回值,还要将对 window.open()的挪用封装在一个 try-catch 块中
var bloacked = false;

try {
  var wroxWin = window.open("http://www.wrox.com", "_blank");
  if (wroxWin == null) {
    bloacked = true;
  }
} catch (ex) {
  bloacked = true;
}

if (blocked) {
  console.log("The popup was blocked!");
}

间歇挪用和超时挪用

  • JavaScript是单线程言语,但它许可经由过程设置超时价和间歇值来调理代码在特定的时刻实行。
// 第一个参数通报字符串,不引荐!
setTimeout('alert("Hello World!");', 1000);

// 引荐的体式格局
setTimeout(() => {
  alert("Hello World!");
}, 1000);
  • JavaScript是一个单线程诠释器,因而肯定时间内只能实行一段代码。为了掌握要实行的代码,就有一个JavaScript使命行列。这些使命会根据将他们增加到行列中的递次实行。
  • 第二个参数是通知JavaScript再过多久把当前使命增加到行列中。今后假如行列是空的,那末增加的代码会马上实行,假如不是空的,那末就要等前面的代码实行完了今后再实行。
  • 该要领会返回一个数值ID,这是设计实行代码的唯一标识符,能够经由过程它来作废超时挪用。
var timeoutId = setTimeout(() => {
  alert("Hello World!");
}, 1000);

// 作废实行
clearTimeout(timeoutId);
  • 超时挪用的代码都是在全局作用域中实行的,因而函数中 this 的值在非严厉形式下 指向 window ,在严厉形式下是 undefined
  • setInterval()用法与上述相似

体系对话框

  • alert(), confirm(), prompt() 要领能够挪用体系对话框向用户显现音讯。体系对话框与阅读器中显现的网页没有关联,不包含HTML,表面由操纵体系和阅读器设置决议。翻开对话框都是同步和模态的。也就是说,这些对话显现的时刻,代码会住手实行,而关掉这些对话框又会恢复实行。
  • confim() 返回一个布尔值,代表用户挑选”ok”照样”cancel”
  • prompt() 返回一个字符串或许null,输入了值并肯定,返回字符串,其他要领封闭返回null
  • 打印、查找 对话框 print() find()。没什么卵用

location对象

  • location是最有用的BOM对象之一,它供应了与当前窗口中加载的文档有关的信息,还供应一些导航功用。
  • location 对象既是window对象的属性,也是document对象的属性;换言之,window.location document.location援用的是同一个对象。
属性名例子申明
hash“#contents”返回 URL 中的hash(#号后跟零或多个字符),假如URL中不包含散列,则返回空字符串
host“www.wrox.com:80”返回服务器称号和端口号(假如有)
hostname“www.wrox.com”返回服务器称号不带端口号
href“http:/www.wrox.com”返回当前加载页面的完全URL。而location对象的toString()要领也返回这个值
pathname“/WileyCDA/”返回URL中的目次或许文件名
port“www.wrox.com”返回端口号。假如没有端口号,返回空字符串
protocol“http:”返回页面运用的协定。平常是 http: https:
search“?q=javascript返回URL查询字符串。这个字符串以问号开首

查询字符串参数

  • 虽然上表的属性能够接见到location对象大多数信息,然则个中接见URL包含查询字符串的属性并不轻易。只管location.search返回从问号到URL末端的一切内容,但却没有办法逐一接见个中的每一个查询字符串参数。
  • 为此我们能够建立以下函数
funcction getQueryStringArgs() {

  // 获得查询字符串并去掉开首的问号
  var qs = (location.search.length > 0 ? location.search.substring(1) : "");

  // 保存数据的对象
  var args = {};

  // 获得每一项
  var items = qs.length ? qs.split("&") : [];
  var item = null;
  var name = null;
  var value = null;

  // 在for轮回中运用
  var i = 0;
  var len = items.length;

  // 逐一将每一项增加到args对象中
  for (var i = 0; i < len; i++) {
    item = items[i].split("=");
    name = decodeURIComponent(item[0]);
    value = decodeURIComponent(item[1]);

    if (name.length) {
      args[name] = value;
    }
  }

  return args;
}

位置操纵

  • 运用location对象能够经由过程许多体式格局来转变阅读器的位置。
  • 起首也是最经常使用的体式格局 assign()要领,并为其通报一个URL。马上翻开新的URL并在阅读器的历史纪录中天生一条纪录。假如是将location.hrefwindow.location设置为一个URL值,也会以该值挪用assign()要领。
location.assign("http://www.wrox.com");
window.location = "http://www.wrox.com";
location.href = "http://www.wrox.com";
  • 别的修正location对象的其他属性也能够转变当前加载的页面。下面的例子展现了经由过程将hash, search, hostname, pathname, prot 属性设置为新值来转变URL
// 假定初始URL为 http://www.wrox.com/WileyCDA/

// 将URL修正为 http://www.wrox.com/wileyCDA/#section1
location.hash = "#section1";

// 将URL修正为 http://www.wrox.com/wileyCDA/?q=javascript
location.search = "?q=javascript";

// 将URL修正为 http://www.wrox.com/wileyCDA/
location.hostname = "www.yahoo.com"

// 将URL修正为 http://www.yahoo.com/mydir/
location.pathname = "mydir"

// 将URL修正为 http://www.yahoo.com:8080/wileyCDA/
location.port = 8080;
  • 每次修正location属性(hash除外),页面都邑以新URL从新加载
  • 经由过程上述任何一种体式格局修正URL今后,阅读器的历史纪录中就会天生一条新纪录,因而用户经由过程单击“退却”按钮都邑导航到前一个页面。要禁用这类行动,能够运用replace()要领。这个要领只吸收一个参数,即要盗号的URL。虽然效果会致使阅读器位置转变,但不会在历史纪录中天生新纪录。在挪用replace()要领后,用户不能回到前一个页面
  • 在IE8 Firefox 1 Safari 2+ Opera9+ Chrome 中,修正hash的值会在阅读器的历史纪录中天生一条纪录。在IE初期版本中,hash属性不会再用户单击“退却”和“行进”按钮时被更新,而只会在用户单击包含hash的URL时才会被更新
  • reload() 作用是从新加载当前页面的显现。假如不传参,页面就会以最有用的体式格局从新加载。假如页面上次要求一来并没有转变过,页面就会从阅读器缓存中从新加载。假如要强迫从服务器从新加载,则须要像下面如许为该要领通报参数true
  • 位于reload()挪用今后的代码能够会也能够不会实行,这要取决于收集耽误或体系资源等要素。为此最好将reload()放在代码的末了一行

navigator对象

  • 每一个阅读器中的navigator对象表现是一致的,也有一套自身的属性
属性或要领申明IEFirefoxSafari/ChromeOpera
appCodeName阅读器的称号。平常都是Mozilla,纵然在非Mozilla阅读器中也是云云3.0+1.0+1.0+7.0+
appMinorVersion次版本4.0+9.5+
appName完全的阅读器称号3.0+1.0+1.0+7.0+
appVersion阅读器的版本。平常不与现实的阅读器版本对应3.0+1.0+1.0+7.0+
buildID阅读器变异版本2.0+
cookieEnabled示意cookie是不是启用4.0+1.0+1.0+7.0+
cpuClass客户端计算机中运用的cpu范例4.0+
javaEnabled()示意当前阅读器中是不是启用了java4.0+1.0+1.0+7.0+
language阅读器的主言语1.0+1.0+7.0+
mineTypes示意当前阅读中注册的MIME范例数组4.0+1.0+1.0+7.0+
onLine示意阅读器是不是衔接到了因特网4.0+1.0+9.5+
oscpu客户端计算机的操纵体系或运用的CPU1.5+
platform阅读器地点的体系平台4.0+1.0+1.0+7.0+
plugins阅读器中装置的插件信息的数组4.0+1.0+1.0+7.0+
preference设置用户的首选项1.5+
product产物称号 如Gecko1.0+1.0+
productSub关于产物的次要信息1.0+1.0+
registerContentHandler()针对特定的MIME范例将一个站点注册为处置惩罚递次2.0+
registerProtocolHandler()针对特定的协定将一个站点注册为处置惩罚递次2.0+
securityPolicy已烧毁。平安策略的称号。为了与Netscape Navigator4向后兼容而保存下来1.0+
systemLanguage操纵体系的言语4.0+
taintEnabled()已烧毁。示意是不是许可变量被修正。为了与Netscape Navigator3向后兼容而保存下来4.0+1.0+7.0
userAgent阅读器的用户代码字符串3.0+1.0+1.0+7.0+
userLanguage操纵体系的默许言语4.0+7.0+
userProfile藉以接见用户个人信息的对象4.0+
vendor阅读器的品牌1.0+1.0+
vendorSub有关供应商的次要信息1.0+1.0+

搜检插件

  • 检测阅读器中是不是装置了特定的插件是一种最常见的检测进程。关于非IE阅读器,能够运用plugins数组来到达这个目标。该数组中的每一项都包含以下属性。

    • name: 插件名字
    • description: 插件的形貌
    • filename: 插件的文件名
    • length: 插件所处置惩罚的MIME范例数目
  • 平常来说name属性中会包含检测插件必须的一切信息,但有时刻也不完全云云。在检测插件时,须要像下面如许轮回代码每一个插件并将插件的name与给定的名字举行比较
// 检测插件(在IE中无效)
function hasPlugin(name) {
  name = name.toLowerCase();
  for (var i=0; i < navigator.plugins.length; i++) {
    if (navigator.plugins[i].name.toLowerCase().indexOf(name) > -1) {
      return true;
    }
  }
  return false;
}

//  检测flash
console.log(hasPlugin("Flash"));

//  检测QuickTime
console.log(hasPlugin("QuickTime"));
  • 检测IE中的插件比较贫苦,因为IE不支撑Netscape式的插件,唯一的体式格局是运用专用的ActiveXObject范例,并尝试建立一个特定插件的实例。IE是以COM对象的体式格局完成插件的,而COM对象运用唯一标识符来标识。因而要想检测特定的插件,就必须晓得其COM标识符,比方Flash的标识符是ShockwaveFlash.ShockwaveFlash。晓得唯一标识符后,就能够编写下面的函数来检测
// 检测IE中的插件
function hasIEPlugin(name) {
  try {
    new ActiveXObject(name);
    return true
  } catch (ex) {
    return false;
  }
}

//  检测flash
console.log(hasIEPlugin("ShockwaveFlash.ShockwaveFlash"));

//  检测QuickTime
console.log(hasIEPlugin("QuickTime.QuickTime"));
  • 鉴于两种体式格局差异较大,典范的做法是针对每一个插件离别建立检测函数
// 检测一切阅读器中的Flash
function hasFlash() {
  var result = hasPlugin("Flash");
  if (!result) {
    result = hasIEPlugin("ShockwaveFlash.ShockwaveFlash");
  }
  return result;
}
  • plugins鸠合有一个名叫refresh()的要领,用于革新plugins以反应最新装置的插件。这个要领吸收一个参数:示意是不是应当从新加载页面的一个布尔值。假如将这个值设为true,则会从新加载包含插件的一切页面;不然只更新plugins鸠合,不从新加载页面。

注册处置惩罚递次

  • registerContentHandler()registerProtocolHandler() 要领能够让一个站点着名它能够处置惩罚特定范例的信息。跟着RSS阅读器和在线电子邮件递次的信息,注册处置惩罚递次就为像运用桌面应用递次一样默许运用这些在线应用递次供应了一种体式格局。
  • registerContentHandler()吸收三个参数:

    • 要处置惩罚的MIME范例
    • 能够处置惩罚的MIME范例的页面的URL
    • 应用递次的称号
// 要将一个站点注册为处置惩罚RSS源的处置惩罚递次
navigator.registerContentHandler("application/rss+xml",
  "http://www.somereader.com?feed=%s", "Some Reader");
  • registerProtocolHandler() 也是三个参数

    • 要处置惩罚的协定 (mailto 或 ftp)
    • 处置惩罚该协定的页面的URL
    • 应用递次的称号
// 要将一个应用递次注册为默许的邮件客户端
navigator.registerProtocolHandler("mailto",
  "http://www.somemailclient.com?cmd=%s", "Some Mail Client");

screen对象

  • screen对象基础只用来表明客户端的才能,个中包含阅读器窗口外部的显现器信息,如像素宽度和高度等。
  • 用途不大

history对象

  • history对象保存着用户上网的历史纪录,从窗口被翻开的那一刻算起。因为historywindow对象的属性,因而每一个阅读器窗口,每一个标签页,以致每一个框架都有自身的history对象与特定的window对象关联。
  • 出于平安斟酌,开发人员没法得知用户阅读器过的URL。不过借由用户接见过的页面列表,一样能够在不晓得现实URL的状况视线退却和行进
  • 运用go()要领能够在用户的历史纪录中恣意跳转,能够向前向后,吸收一个参数整数值或许字符串。
// 退却一页
history.go(-1);

// 行进一页
history.go(1);

// 行进两页
history.go(2);

// 传入字符串会跳转到历史纪录中包含该字符串的第一个位置
// 假如没有包含的纪录,则什么都不做
history.go("wrox.com");
  • 还能够运用两个简写要领替代 back()forward()。这两个要领模拟阅读器的“退却”“行进”按钮
  • history另有一个length属性,保存着历史纪录的数目。包含一切的历史纪录,即一切向前和向后的纪录。关于加载到窗口、标签页或框架中的第一个页面而言,hitosty.length即是0
if (history.length == 0) {
  // 这里应当是用户翻开窗口后的第一个页面
  ...
}
    原文作者:陈思达
    原文地址: https://segmentfault.com/a/1190000019195392
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞