关于前端:JavaScript高级程序设计笔记12-BOM

2次阅读

共计 17243 个字符,预计需要花费 44 分钟才能阅读完成。

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 defined
var 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 属性提供。

例子🌰:

手机屏幕的物理分辨率为 1920×1080,浏览器转换为逻辑分辨率为 640×320,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"));

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

// 在所有浏览器中检测 Flash
function 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 模式?)

正文完
 0