BOM

BOM的外围——window对象

窗口和弹窗

location对象——页面信息

navigator对象——浏览器信息

history对象——浏览器历史记录

BOM是应用JavaScript开发Web应用程序的外围。提供了与网页无关的浏览器性能对象。

浏览器实现之间共通的局部成为了事实标准,为Web开发提供了浏览器间互操作的根底。

HTML5标准,涵盖了BOM的次要内容,心愿将JavaScript在浏览器中最根底的局部标准化。

window对象

示意浏览器的实例。在浏览器中有两重身份:

一个是ECMAScript中的Global对象,

另一个是浏览器窗口的JavaScript接口。

因为window对象的属性在全局作用域中无效,所以很多浏览器API及相干构造函数都以window对象属性的模式裸露进去。

Global作用域

通过var申明的所有全局变量和函数都会变成window对象的属性和办法。

如果应用let或const代替var,则不会把变量增加给全局对象。

拜访未声明的变量会抛出谬误,但能够在window对象上查问是否存在可能未声明的变量,如:

var newValue = oldValue; // 抛出谬误 ReferenceError: oldValue is not definedvar newValule = window.oldValue; // undefined

窗口关系

top对象始终指向最上层(最外层)窗口,即浏览器窗口自身。

parent对象始终指向以后窗口的父窗口。如果以后窗口是最上层窗口,则parent等于top(都等于window)。最上层的window如果不是通过window.open()关上的,那么其name属性就不会蕴含值。

self对象,是终极window属性,始终会指向window。实际上,self和window是同一个对象。

这能够把拜访多个窗口的window对象串联起来。(嵌套iframe页面)

窗口地位与像素比

  1. 获取地位,挪动地位

古代浏览器提供了screenLeft和screenTop属性,用于示意窗口绝对于屏幕左侧和顶部的地位,返回值的单位是CSS像素

能够应用moveTo()和moveBy()办法挪动窗口。都接管两个参数,moveTo接管要挪动到的新地位的相对坐标x和y;moveBy接管绝对以后地位在两个方向上挪动的像素数。

测试:FF可用——条件:通过window.open()关上,且只有一个标签页;Chrome不可用。

第一个参数,为负向左挪动,为正则向右挪动;第二个参数,为负向上挪动,为正则向下挪动。

依浏览器而定,可能会被局部或全副禁用。

  1. 像素比

不同像素密度的屏幕下就会有不同的缩放系数,以便把物理像素(屏幕理论的分辨率)转换为CSS像素(浏览器报告的虚构分辨率)。

物理像素与CSS像素之间的转换比率由window.devicePixelRatio属性提供。

例子:

手机屏幕的物理分辨率为1920x1080,浏览器转换为逻辑分辨率为640x320,window.devicePixelRatio的值就为3。这样一来,12px的文字实际上就会用36的物理像素来显示。

window.devicePixelRatio实际上与每英寸点数(DPI,dots per inch)是对应的。DPI示意单位像素密度,而window.devicePixelRatio示意物理像素与逻辑像素之间的缩放系数。

扩大学习:

屏幕尺寸:指的是屏幕对角线的长度

分辨率:是指宽度上和高度上最多能显示的物理像素点个数

PPI(pixel per inch): 屏幕像素密度,即每英寸(1英寸=2.54厘米)汇集的像素点个数,这里的一英寸还是对角线长度

DPI: 每英寸像素点,印刷行业术语。对于电脑屏幕而言和PPI是一个意思

设施像素(又称为物理像素 device pixels,dp): 指设施能管制显示的最小物理单位,意指显示器上一个个的点。从屏幕在工厂生产出的那天起,它下面设施像素点就固定不变了,和屏幕尺寸大小无关,单位 pt。

设施独立像素(也叫密度无关像素或逻辑像素device-independent pixel,简称DIPs):能够认为是计算机坐标零碎中得一个点,这个点代表一个能够由程序应用的虚构像素(比方: css像素),这个点是没有固定大小的,越小越清晰,而后由相干零碎转换为物理像素。

css像素(也叫虚构像素):指的是 CSS 款式代码中应用的逻辑像素,在 CSS 标准中,长度单位能够分为两类,相对(absolute)单位以及绝对(relative)单位。px 是一个绝对单位,绝对的是设施像素(device pixel)

DPR(设施像素比):设施像素比 = 设施像素 / 设施独立像素。(在Retina屏的iphone上,DPR为2,1个css像素相当于2个物理像素) 1px => 2dp

以iphone6为例

iPhone6的设施宽度和高度为375pt * 667pt,能够了解为设施的独立像素(相似css像素);而其dpr为2,依据下面公式,咱们能够很轻松得悉其物理像素为750pt * 1334pt

对于这样的css款式:

width: 2px;

height: 2px;

在不同的屏幕上(一般屏幕 vs retina屏幕),css像素所出现的大小(物理尺寸)是统一的,不同的是1个css像素所对应的物理像素个数是不统一的。

在一般屏幕下,1个css像素 对应 1个物理像素(1:1)。

在retina 屏幕下,1个css像素对应 4个物理像素(1:4)。 1px² => 4 dp²

dpr = 物理像素dp/设施独立像素dip(px)

依据dpr不同,设置其缩放为dpr倒数,设置页面缩放能够使得1个CSS像素(1px)由1个设施像素来显示,从而进步显示精度;因而,设置1/dpr的缩放视口,能够画出1px的边框;

窗口大小

window.innerWidth和window.innerHeight返回浏览器窗口中页面视口(可见视口)的宽度和高度(不蕴含浏览器边框和工具栏,蕴含滚动条的地位)。(挪动端默认是写死的宽度,通过<meta name="viewport">设置content能够设置,通常挪动端页面会设置为width=device-width设置为和设施宽度( layout-viewport-width,iphone6为375)雷同,设置scale=1/dpr时,相当于放大css像素,使1个css像素对应1个物理像素,设置scale=1时,相当于应用1个css像素对应dpr个物理像素)。

innerWidth = 375 / scale = 750px; innerWidth 分成 10rem, font-size = innerWidth / 10 = 75px

window.outerWidth和window.outerHeight返回浏览器窗口本身的大小。(挪动端的屏幕宽度,固定不变)

document.documentElement.clientWidth和document.documentElement.clientHeight返回页面视口的宽度和高度(不蕴含滚动条的地位)(返回布局视口的大小,即渲染页面的理论大小,MobileIE返回的是可见视口的大小)。

document.compatMode=="CSS1Compat",可用于查看页面是否处于规范模式。如果是,应用document.docmentElement.clientWidth和clientHeight;否则应用document.body.clientWidth和clientHeight。

window.innerWidth和innerHeight(可见视口的大小),以及document.documentElement.clientWidth和clientHeight(在Mobile Internet Explorer中返回的是可见视口的大小,在其余挪动浏览器中返回的是布局视口的大小),在放大或放大页面时,这些值也会相应变动。Mobile Internet Explorer中把布局视口的信息保留在document.body.clientWidth和clientHeight中,放大或放大页面时,这些值也会相应变动。

能够应用resizeTo()和resizeBy()办法调整窗口大小。都接管两个参数,resizeTo()接管新的宽度和高度,resizeBy()接管宽度和高度要缩放多少。resizeBy()接管负的参数示意放大,正的参数示意放大。测试:FF可用——条件:通过window.open()关上,且只有一个标签页;Chrome不可用。只能利用到最上层的window对象。

视口地位

用户能够通过滚动在无限的视口中查看文档。

度量文档绝对于视口滚动间隔的属性有两对,返回相等的值:window.pageXOffset/window.scrollX和window.pageYOffset/window.scrollY。

能够应用scroll()、scrollTo()和scrollBy()办法滚动页面。这3个办法都接管示意绝对视口间隔的x和y坐标。前两个办法的两个参数示意要滚动到的坐标,最初一个示意滚动的间隔。

这几个办法也都接管一个scrollToOptions字典,除了提供偏移量,还能够通过behavior属性通知浏览器是否平滑滚动。

scrollBy({left:100, top: 500, behavior: 'smooth'});scrollTo({left:100, top: 500, behavoir: 'smooth'});// scroll()和scrollTo()成果类似

导航与关上新窗口

  1. 弹窗(如何关上一个窗口,以及如何敞开它)

window.open():导航到指定URL。接管四个参数:要加载的URL、指标窗口、个性字符串和示意新窗口在浏览器历史记录中是否代替以后加载页面的布尔值。

通常传前3个参数,第4个参数只有在不关上新窗口时才会应用。

第2个参数如果是一个曾经存在的窗口或frame的名字,则会在对应的窗口或frame中关上URL(与a标签中的target属性作用雷同);否则就会关上一个新窗口并将其命名为第2个参数指定的名称。第二个参数也能够是一个非凡的窗口名,如_self、_parent、_top或_blank。

第3个参数(个性字符串),用于指定新窗口的配置,是一个逗号分隔的设置字符串。如果关上的不是新窗口,会被疏忽。(以逗号分隔的名值对,名值对以等号连贯)

  • fullscreen。yes或no。是否最大化,仅IE反对
  • height。数值。新窗口的高度,不小于100。测试:FF和Chrome有成果
  • width。数值。新窗口的宽度,不小于100。
  • left。数值。新窗口的x轴坐标,不能为负。测试:FF和Chrome有成果
  • top。数值。新窗口的y轴坐标,不能为负。测试:FF和Chrome有成果
  • location。yes或no。是否显示地址栏,不同浏览器的默认值不同。测试:FF和Chrome会显示地址栏,然而只读
  • Menubar。yes或no。是否显示菜单栏,默认为no。测试:ff和Chrome如同没影响?
  • resizable。yes或no。是否能够拖动扭转新窗口大小。测试:设置no,ff和Chrome如同没影响?
  • scrollbars。yes或no。是否能够在内容过长时滚动。
  • status。yes或no。是否显示状态栏。
  • toolbar。yes或no。是否显示工具栏。
self.parent.open('./c12-sub2.html', "newWindow", "location=yes,height=200,left=100,top=0,width=500,Menubar=yes,resizable=no"); // ff和Chrome,设置个性字符串,能够弹出新窗口;否则关上新标签页

window.open()办法返回一个对新建窗口的援用。为管制新窗口提供了不便。

还能够应用close()办法敞开新关上的窗口。

<button id="openSub">open Sub Sub Page</button><button onclick="closeSubWindow();">close Sub Sub Page</button><script>    let a;    document.querySelector('#openSub').addEventListener('click', () => {        a = self.parent.open('./c12-sub2.html', "newWindow");    });    function closeSubWindow() {        a.close();        alert(a.closed); // true    }</script>

只能用于window.open()创立的弹出窗口。弹出窗口能够调用top.close()来敞开本人。

// Scripts may close only the windows that were opened by them.

敞开后的窗口,只能用于查看其closed属性。

新创建窗口的window对象有一个属性opener,指向关上它的窗口。这个属性只在弹出窗口的最上层window对象(top)有定义,是指向调用window.open()关上它的窗口或frame的指针。

窗口不会跟踪记录本人关上的新窗口,如有须要开发者要本人记录。

把opener设置为null,示意新关上的标签页不须要与关上它的标签页通信,因而能够在独立过程中运行。(不可逆)

  1. 平安限度(浏览器对弹窗的限度

IE晚期版本实现对弹窗的多重平安限度(在线广告的滥用),包含不容许创立弹窗或者把弹窗移出屏幕外,以及不容许暗藏状态栏等。IE7开始,地址栏也不能暗藏了,而且弹窗默认不能挪动或者缩放。

IE对关上本地网页的窗口再弹窗解除了某些限度,如果代码来自服务器,会施加弹窗限度。

ff1禁用了暗藏状态栏的性能,ff3强制弹窗始终显示地址栏。

Opera只会在主窗口中关上新窗口,但不容许它们呈现在零碎对话框的地位。

浏览器会在用户操作下才容许创立弹窗。

  1. 弹窗屏蔽程序(检测弹窗是否被屏蔽

所有古代浏览器都内置了屏蔽弹窗的程序。如果弹窗被阻止,window.open()可能会返回null。只有查看这个办法的返回值就能够晓得弹窗是否被屏蔽了。

在浏览器扩大或其余程序屏蔽弹窗时,window.open()通常会抛出谬误。所以要精确检测弹窗是否被屏蔽,还须要用try/catch包裹起来。

let blocked = false;try {  let win = window.open('xxxxx');  if(win == null) {    blocked = true;  }} catch(ex) {  blocked = true;}if(blocked) {  alert("The popup was blocked!");}

定时器

JavaScript在浏览器中是单线程执行的,但容许应用定时器指定在某个工夫之后或每隔一段时间就执行相应的代码。

setTimeout()——通常接管两个参数:要执行的代码和在执行回调函数前期待的工夫(毫秒)。第一个参数能够是蕴含JavaScript代码的字符串或者一个函数;第二个参数是要期待的毫秒数,不是执行代码的确切工夫。——返回一个示意该超时排期的数值ID,该超时ID是这被排期执行代码的惟一标识符,可用于勾销该工作(clearTimeout)。

为了调度代码的执行,JavaScript保护了一个工作队列。其中的工作会依照增加到队列的先后顺序执行,如果队列是空的,就会立刻执行;如果非空,须要期待后面的工作执行完能力执行。

所有超时执行的代码(函数)都会在全局作用域中的一个匿名函数中运行(IIFE?)。

setInterval()——每隔指定工夫就执行一次代码,直到勾销循环定时或者页面卸载。——会返回一个循环定时ID,可用于在将来某个工夫点上勾销循环定时(clearInterval)。

浏览器不关怀工作什么时候执行或者执行要花多长时间。因而,执行工夫短、非阻塞的回调函数比拟适宜setInterval()。应用setTimeout()会在条件满足时主动进行,否则会主动设置另一个超时工作。这个模式是设置循环工作的举荐做法。setInterval()很少用于生产环境,因为一个工作完结和下一个工作开始的工夫距离无奈保障。

零碎对话框

alert()、confirm()和prompt()办法,能够让浏览器调用零碎对话框向用户显式音讯。外观由操作系统或者浏览器决定,无奈应用CSS设置。此外 ,这些都是同步的模态对话框,调用时代码会中断执行,敞开后代码复原执行。

正告框:alert()——只接管一个参数。如果参数不是一个原始字符串,则调用这个值的toString()办法将其转换为字符串。——通常用于向用户显示一些他们无法控制的音讯,如报错。用户惟一可选的操作就是敞开。

确认框:confirm()——有两个按钮:Cancel和OK,用户通过单击不同的按钮表明心愿接下来执行什么操作。返回值为布尔值,true示意单击了OK按钮,false示意单击了Cancel或者敞开了确认框。——通常用于让用户确认执行某个操作。

提示框:prompt()——提醒用户输出音讯。除了Cancel和OK两个按钮,还会显示一个文本框。接管两个参数:显示给用户的文本,以及文本框的默认值(能够是空字串)。如果提示框被敞开,会返回null;否则点击OK按钮,返回文本框中的值。

Web应用程序最简略快捷的沟通伎俩。

很多浏览器针对零碎对话框增加了非凡性能。如有多个零碎对话框,则除第一个以外后续的对话框都会显示一个复选框,如果用户选中则会禁用后续的弹框,直到页面刷新。开发者无奈获悉这些对话框是否显示了。

JavaScript还能够显示另外两种对话框:find()(查找对话框)和print()(打印对话框)。都是异步显式,即控制权会立刻返回给脚本。两者都不会返回任何无关用户在对话框中执行了什么操作的信息。浏览器的对话框计数器不会波及它们,并且用户抉择禁用对话框对它们也没有影响。

<!-- c12-bom.html --><!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <meta name="viewport" content="width=device-width">    <title>BOM Main Page</title>    <style>        html { font-size: 1px; }        * { padding: 0; margin: 0; }        .top_b { border-bottom: 1px solid #E5E5E5; }        .a,.b { box-sizing: border-box; margin-top: 1rem; padding: 1rem; font-size: 1.4rem; }        .a { width: 100%; }        .b { background: #f5f5f5; width: 100%; }    </style></head><body><button id="openSub" style="font-size: 12px;">open Sub Page</button><div style="width: 10vw; height: 1px; background-color: cyan;"></div><iframe src="./c12-sub.html" frameborder="0"></iframe><!--上面的底边宽度是虚构1像素的 下面的边框宽度是虚构1像素的--><script>    var viewport = document.querySelector("meta[name=viewport]");    //上面是依据设施像素设置viewport    alert(`window.devicePixelRatio: ${window.devicePixelRatio}`);    if (window.devicePixelRatio == 1) {        viewport.setAttribute('content', 'width=device-width,initial-scale=1, maximum-scale=1, minimum-scale=1, user-scalable=no');    }    if (window.devicePixelRatio == 2) {        viewport.setAttribute('content', 'width=device-width,initial-scale=0.5, maximum-scale=0.5, minimum-scale=0.5, user-scalable=no');    }    if (window.devicePixelRatio == 3) {        document.querySelector('#openSub').style.fontSize = "18px";        viewport.setAttribute('content', 'width=device-width,initial-scale=0.3333333333333333, maximum-scale=0.3333333333333333, minimum-scale=0.3333333333333333, user-scalable=no');    }    var docEl = document.documentElement;    var fontsize = 32* (docEl.clientWidth / 750) + 'px';    docEl.style.fontSize = fontsize;</script><script>  /*  var age = 29;  var sayAge = () => alert(this.age);  alert(window.age); // 29  sayAge(); // 29  window.sayAge(); // 29  *//*  let age = 29;  const sayAge = () => alert(this.age);  alert(window.age); // undefined  sayAge(); // undefined  window.sayAge(); // TypeError: window.sayAge is not a function*/    document.querySelector('#openSub').addEventListener('click', () => {        window.open('./c12-sub.html');    });    alert(`${window.innerWidth}, ${window.innerHeight}`);    /*setTimeout(()=> {          window.moveBy(0, 100);          alert(getComputedStyle(document.querySelector('#openSub'))["font-size"]);      }, 2000);*/</script></body></html>
<!-- c12-sub.html --><!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>BOM Sub Page</title></head><body><button id="openSub">open Sub Sub Page</button><button onclick="closeSubWindow();">close Sub Sub Page</button><iframe src="./c12-sub2.html" frameborder="0" name="innerFrame"></iframe><script>    let a;    document.querySelector('#openSub').addEventListener('click', () => {        a = self.parent.open('./c12-sub2.html', "newWindow"); // self.parent.open('./c12-sub2.html', "newWindow");    });    function closeSubWindow() {        a.close();        alert(a.closed);    }    console.log(top);    console.log(parent);    console.log(self);    console.log(self.outerWidth);    console.log(self.innerWidth);    console.log(parent.innerWidth);</script></body></html>
<!-- c12-sub2.html --><!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>BOM Sub Sub Page</title>    <script>        function goSub2() {            // self.parent.open('./c12-sub2.html', "_parent");            self.parent.open('./c12-sub2.html', "newWindow", "location=yes,height=200,left=100,top=0,width=500,Menubar=yes,resizable=no");        }        function goSub() {            // self.parent.open('./c12-sub.html', "newWindow");            self.parent.open('./c12-sub.html', "innerFrame");        }        function closeSelf() {            top.close();        }    </script></head><body><p>I am sub2.</p><button onclick="goSub2();">open sub2</button><button onclick="goSub();">open sub</button><a href="./c12-sub.html" target="newWindow">to sub</a><button onclick="closeSelf();">close self</button><script>    console.log(top);    console.log(parent);    console.log(self);    // setTimeout(()=> self.parent.open('./c12-sub.html'), 1000);</script></body></html>
<!-- use-flexible.html --><!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>c12-test-flexible</title>    <script src="./utils/flexible.js"></script>    <style>        #one {            border: 1px solid #333;        }        .small {            position: relative;            height: 1rem;            border: 1px solid #333;        }        .small::after {            position: absolute;            bottom: 4px;            left: 1px;            content: "";            width: 1rem;            height: 1px;            background-color: #000;            transform: scale(0.5);        }        [data-dpr="1"] .small {            font-size: 12px;        }        [data-dpr="2"] .small {            font-size: 24px;        }    </style></head><body>  <p style="font-size: .5rem;">font-size: .5rem;</p>  <p style="font-size: 1rem;" id="one">font-size: 1rem;</p>  <p class="small">font-size: 12px;</p>  <p style="font-size: 1.5rem;">font-size: 1.5rem;</p>  <p style="font-size: 2rem;">font-size: 2rem;</p>  <p style="font-size: 2.5rem;">font-size: 2.5rem;</p>  <script>    alert(document.documentElement.style.fontSize);    alert(window.innerWidth);    alert(window.outerWidth);    setTimeout(()=> alert(getComputedStyle(document.querySelector('#one')).fontSize), 2000);  </script></body></html>

location对象

提供了以后窗口中加载文档的信息,以及通常的导航性能。

既是window的属性,也是document的属性。window.location和document.location指向同一个对象。

不仅保留着以后加载文档的信息,也保留着把URL解析为离散片段后可能通过属性拜访的信息。

  • location.hash。URL散列值(#号后跟0或多个字符,#号结尾),没有则为空串
  • location.host。服务器名及端口号
  • location.hostname。服务器名
  • location.href。以后加载页面的残缺URL。是location.toString()的返回值
  • location.pathname。URL中的门路和(或)文件名(host之后search之前的一段字符串?)
  • location.port。申请的端口。没有则返回空串
  • location.protocol。页面应用的协定。通常是http:和https:
  • location.search。URL的查问字符串。以问号结尾([?到#)之间)
  • location.username。域名前指定的用户名(???)
  • location.password。域名前指定的明码(???)
  • location.origin。URL的源地址。只读。截取href从协定到host的字符串(?)

http://foouser:[email protected]:80/WileyCDA/?q=javascript#contents

查问字符串

需要:一一拜访每个查问参数

罕用

let getQueryStringArgs = function() {  let qs = (location.search.length > 0 ? location.search.substring(1) : ""),      args = {};  for (let item of qs.split("&").map(kv => kv.split("="))) { // 用&宰割成数组,元素的模式为name=value,再用map映射出新数组,元素的模式为[name, value]    let name = decodeURIComponent(item[0]), // 查问字符串通常是被编码后的格局        value = decodeURIComponent(item[1]);    if(name.length) {      args[name] = value;    }  }  return args;}

URLSearchParams

提供了一组规范API办法,能够检查和批改查问字符串。给URLSearchParams构造函数传入一个查问字符串,就能够创立一个实例(new操作)。实例办法有get()、set()和delete()、has()等办法,可对查问字符串执行相应操作(相似Map?)。实例可用作可迭代对象(for...of)

操作地址

通过批改location对象批改浏览器的地址。

  • 最常见(间接批改):应用assign()办法并传入一个URL。location.assgin("xxx://xxxx");

    会立刻启动导航到新URL的操作,同时在浏览器历史记录中减少一条记录(当前页)。

    给location.href或window.location设置一个URL,会以同一个URL值调用assign()办法。

    批改location对象的属性也会批改以后加载的页面。其中,hash、search、hostname、pathname和port属性被设置为新值之后都会批改以后URL;除了hash之外,只有批改location的一个属性,就会导致页面从新加载新URL(单页利用通常利用hash模仿后退后退,不会因导航而触发页面刷新)

  • replace()办法。不减少历史记录。接管一个URL参数。调用之后不能返回到前一页。(后退按钮或history.go(-1)或history.back()不能回到前一页)
  • reload()办法。不传参数的话,页面会以最无效的形式从新加载(不减少历史记录) :如果页面自上次申请以来没有批改过,浏览器可能会从缓存中加载页面。如果想强制从服务器从新加载,能够给办法传个true

    reload()调用之后的代码可能执行也可能不执行,取决于网络提早和系统资源等因素。最好把reload()作为最初一行代码。

navigator对象

客户端标识浏览器的规范。

只有浏览器启用JavaScript,navigator对象就肯定存在。

一些定义的属性和办法:

  • appVersion。浏览器版本,通常与理论的浏览器版本不统一(???)

    Chrome打印:"5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36"

    ff打印:"5.0 (Macintosh)"

  • geolocation。返回裸露Geolocation API的Geolocation对象
  • plugins。浏览器装置的插件数组。
  • share()。返回以后平台的原生共享机制(测试:Chrome和ff没有?)
  • userAgent。返回浏览器的用户代理字符串

    ff打印:"Mozilla/5.0 (Macintosh; Intel Mac OS X 10.16; rv:86.0) Gecko/20100101 Firefox/86.0"

    Chrome打印:"Mozilla/5.0 (Macintosh; Intel Mac OS X 11_2_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.128 Safari/537.36"

  • vendor。返回浏览器的厂商名称

    ff打印:空串

    Chrome打印:"Google Inc."

  • vendorSub。返回浏览器厂商的更多信息
  • vibrate()。触发设施振动
  • webdriver。返回浏览器以后是否被自动化程序控制

navigator对象的属性通常用于确定浏览器的类型

检测插件

检测浏览器是否装置了某个插件。(除IE10及更低版本外的浏览器)。plugins数组中的每一项都蕴含如下属性:

  • name:插件名称
  • description:插件介绍
  • filename:插件的文件名
  • length:由以后插件解决的MIME类型数量

name属性蕴含辨认插件所需的必要信息,只管不是特地精确。检测插件就是遍历浏览器中可用的插件,并一一比拟插件的名称。如下:

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;}alert(hasPlugin("Flash"));alert(hasPlugin("QuickTime"));

以上办法可在ff、Safari、Opera和Chrome中检测插件。

plugins数组中的每个插件对象还有一组MimeType对象,能够通过中括号拜访(数值下标)。每个MimeType对象有四个属性:description形容MIME类型,enabledPlugin是指向插件对象的指针,suffixes是该MIME类型对应扩展名的逗号分隔的字符串,type是残缺的MIME类型字符串。

IE11中的ActiveXObject也从DOM隐身了,不能再用于检测个性。

旧版本IE中的插件检测

不反对Netscape式的插件。要应用专有的ActiveXObject,并尝试实例化特定的插件。IE中的插件是实现为COM对象的,由惟一的字符串标识。因而,要检测某个插件就必须晓得其COM标识符。

function hasIEPlugin(name) {  try {    new ActiveXObject(name); // 应用传入的标识符创立一个新ActiveXObject实例    return true;  } catch(ex) {    return false;  }}alert(hasIEPlugin("ShckwaveFlash.ShockwaveFlash"));alert(hasIEPlugin("QuickTime.QuickTime"));

因为检测插件波及两种形式,所以个别要针对特定插件写一个函数。

// 在所有浏览器中检测Flashfunction hasFlash() {  var result = hasPlugin("Flash");  if(!result) {    result = hasIEPlugin("ShockwaveFlash.ShockwaveFlash");  }  return result;}

注册处理程序

古代浏览器反对navigator上的registerProtocolHandler()办法。能够把一个网站注册为解决某种特定类型信息应用程序。(在线RSS阅读器和电子邮件客户端)注册为像桌面软件一样的默认应用程序。

必须传入3个参数:要解决的协定(如“mailto”或“ftp”)、解决该协定的URL,以及利用名称。

navigator.registerProtocolHandler("mailto", "http://www.somemailclient.com?cmd=%s", "Some Main Client");

上例为mailto协定注册了一个处理程序,邮件地址能够通过指定的Web应用程序关上。第二个参数是负责解决申请的URL,%s示意原始的申请。

screen对象

在编程中很少用的JavaScript对象。保留的纯正是客户端能力信息,即浏览器窗口里面的客户端显示器的信息。如像素宽度和像素高度。每个浏览器会在screen对象上裸露不同的属性。通常用于评估浏览网站的设施信息。

  • availHeight/Left/Top/Width:没有被零碎组件占用的屏幕的高度/最左侧像素/最顶部像素/宽度
  • colorDepth:屏幕色彩的位数:少数零碎是32
  • height/left/top/width:屏幕像素高度/右边的像素间隔/顶部的像素间隔/像素高度
  • pixelDepth:屏幕的位数
  • orientation:返回Screen Orientation API中屏幕的朝向。

history对象

用于示意以后窗口首次应用以来用户的导航历史记录。每个window对象都有本人的history对象。出于平安,不会裸露用户拜访过的URL,但能够通过它来后退和后退。(操纵浏览器历史记录的能力,以编程形式实现在历史记录中导航)

导航

go()——能够在用户历史记录中沿任何方向导航,能够后退也能够后退。只接管一个参数,为整数时示意后退或后退多少步;为字符串时,会导航到历史中蕴含该字符串的第一个地位(可能后退也可能后退)。——如果没有匹配项就什么也不做。

两个简写办法:back()(后退一页)和forward()(后退一页)。模仿了浏览器的后退按钮和后退按钮。

length属性——示意历史记录中有多少个条目,历史记录的数量。对于窗口或标签页中加载的第一个页面,length等于1。通过测试这个值,能够确定用户浏览器的终点是不是你的页面。

history对象通常被用于创立”后退“和“后退”按钮,以及确定页面是不是用户历史记录中的第一条记录。

历史状态治理

历史记录治理。

hashchange事件(17章)。HTML5也为history对象减少了不便的状态治理个性。

hashchange会在页面URL的散列变动时被触发。而状态治理API能够让开发者扭转浏览器URL而不会加载新页面

能够应用history.pushState()办法:接管3个参数(一个state对象、一个新状态的题目和一个(可选的)绝对URL)。办法执行后,状态信息就会被推到历史记录中,浏览器地址栏也会扭转以反映新的绝对URL。

let stateObject = {foo: 'bar'};history.pushState(stateObject, "My title", "web");

不会向服务器发送申请。第二个参数临时没用。第一个参数示意状态的对象大小是有限度的,通常是500K~1M。

pushState()会创立新的历史记录(影响history对象)。单击“后退”会触发window对象上的popstate事件,对应的事件对象有一个state属性,其中蕴含通过pushState()第一个参数传入的state对象。

window.addEventListener("popstate", event => {  let state = event.state;  if(state) { // 默认为null    processState(state);  }});

基于这个状态,应该把页面重置为状态对象所示意的状态。页面首次加载时没有状态。

也能够应用replaceState()并传入两个参数(state、title)来更新状态。更新状态不会创立新历史记录,只会笼罩以后状态。

state对象应该只蕴含能够被序列化的信息。

应用HTML5状态治理时,要确保通过pushState()创立的每个“假”URL背地都对应着服务器上一个实在的物理URL。否则,单击“刷新”按钮会导致404谬误。(history模式?)