## 一、BOM
### 1、定義
瀏覽器對象模型BOM(Browser Object Model),它使 JavaScript 有能力與瀏覽器進行“對話”,控制瀏覽器行為(跳轉,前進,后退,獲取屏幕大小等)
### 2、結構
- BOM是Browser Object Model的縮寫,簡稱瀏覽器對象模型
- BOM提供了獨立于內容而與瀏覽器窗口進行交互的對象
- 由于BOM主要用于管理窗口與窗口之間的通訊,因此其核心對象是window
- BOM由一系列相關的對象構成,并且每個對象都提供了很多方法與屬性
- BOM缺乏標準,JavaScript語法的標準化組織是ECMA,DOM的標準化組織是W3C(WHATWG,WebHypertextApplicationTechnologyWorkingGroup——網頁超文本應用程序技術工作組目前正在努力促進BOM的標準化)
- BOM最初是Netscape瀏覽器標準的一部分
結構圖如下:

BOM提供了可以訪問窗口對象的一些方法,我們可以用它來移動窗口位置,改變窗口大小,打開新窗口和關閉窗口,彈出對話框,進行導航以及獲取客戶的一些信息如:瀏覽器品牌、版本,屏幕分辨率等。但BOM最強大的功能是它提供了一個訪問HTML頁面的入口——document對象,以使得我們可以通過這個入口來使用DOM的強大功能。
### 3、BOM對象用法小結
#### (一) window 對象
window對象是BOM的頂層(核心)對象,所有對象都是通過它延伸出來的,也可以稱為window的子對象。由于window是頂層對象,因此調用它的子對象時可以不顯示的指明window對象,window對象表示整個瀏覽器窗口,但不必表示其中包含的內容。此外,window還可用于移動或調整它表示的瀏覽器的大小,或者對它產生其他影響。
##### 1. window 對象的屬性:
屬性 | 描述
---|---
closed | 返回窗口是否已被關閉
defaultStatus | 設置或返回窗口狀態欄中的默認文本
frames| 返回窗口中所有命名的框架。該集合是 Window 對象的數組,每個 Window 對象在窗口中含有一個框架
length | 設置或返回窗口中的框架數量
name | 設置或返回窗口的名稱
opener | 返回對創建此窗口的窗口的引用
parent | 返回父窗口
self | 返回對當前窗口的引用。等價于window屬性
status | 設置窗口狀態欄的文本
top | 返回最頂層的父窗口
screenX | 設定窗口距離屏幕左邊界的像素長度
screenY | 設定窗口距離屏幕上邊界的像素長度
screenLeft | 等價于window.screenX
screenTop | 等價于window.screenY
outerHeight | 返回窗口的外部高度
outerWidth | 返回窗口的外部寬度
innerHeight | 返回窗口的文檔顯示區的高度
innerWidth | 返回窗口的文檔顯示區的寬度
pageXoffset | 設置或返回當前頁面相對于窗口顯示區左上角的X位置(此方法只有IE支持)
pageYoffset | 設置或返回當前頁面相對于窗口顯示區左上角的Y位置 (此方法只有IE支持)
##### 2. window 對象的方法:
方法 | 描述
---|---
alert() | 彈出一個帶有一段消息和確認按鈕的窗體
confirm() | 顯示帶有一段消息以及確認按鈕盒取消按鈕的對話框
prompt() | 顯示可提示用戶輸入的對話框
focus() | 把鍵盤焦點給予一個窗口
blur() | 把鍵盤焦點從頂層窗口移開
open() | 打開一個新的瀏覽器窗體
close() | 關閉瀏覽器窗口
forward() | 模擬用戶點擊瀏覽器上的“前進”按鈕,將頁面轉到瀏覽器的下一頁
back() | 模擬用戶點擊瀏覽器上的“后退”按鈕,將頁面轉到瀏覽器的上一頁
home() | 模擬用戶點擊瀏覽器上的“主頁”按鈕,將頁面轉到指定的頁面上
stop() | 模擬用戶點擊瀏覽器上的“停止”按鈕,終止瀏覽器的下載操作
print() | 模擬用戶點擊瀏覽器上的“打印”按鈕,通知瀏覽器打開打印對話框打印當前頁
resizeBy() | 按照指定的像素調整窗口的大小
resizeTo() | 把窗體的大小調整到指定的寬度和高度
moveBy() | 可相對窗口的當前坐標移動指定的像素
moveTo() | 把窗口的左上角移動到一個指定的坐標
scrollBy() | 按照指定的像素值來滾動內容
scrollTo() | 把內容滾動到指定的坐標
setInterval() | 按照指定的周期(毫秒)來調用函數或計算表達式
setTimeout() | 在指定的毫秒數后調用函數或表達式
clearInterval() | 取消由setInterval()設置的timeout
clearTimeout() | 取消由setTimeout()方法設置的timeout
計時器:
```
<script>
var timer = null;
function printTime () {
var d = new Date();
var h= d.getHours();
var m= d.getMinutes();
var s= d.getSeconds();
document.getElementById("time").innerHTML = h + ":" + m+ ":" + s;
}
function begin () {
timer = setInterval(printTime,1000)
}
function pause () {
clearInterval(timer)
}
</script>
<div id="time"></div>
<button onclick='begin()'>開始</button>
<button onclick='pause()'>暫停</button>
```
#### (二) window的子對象
##### 1. History 對象
History 對象包含用戶(在瀏覽器窗口中)訪問過的 URL
**(1)對象屬性:**
屬性 | 描述
---|---
length | 返回瀏覽器歷史列表中的 URL 數量
state | 表示當前地址欄中網址對應的狀態
**(2)對象方法:**
方法 | 描述
---|---
history.back() | 回退一個地址,相當于瀏覽器的后退鍵;對第一個網址無效。
history.forward()| 前進一個地址,相當于瀏覽器的前進鍵;對最后一個網址無效。
history.go(n) | 當n>0時,前進n個歷史記錄;當n>history.length時,失效。當n=0時,go(0);刷新當前頁面。當n<0時,后退n個歷史記錄;當n>history.length時,失效。
history.pushState(state, title, url) | 可以改變當前地址欄的url,且在歷史記錄中添加一條;不會刷新頁面。
history.replaceState(state, title, url) | 功能是修改history對象的當前記錄。其他參數和pushState相同,不會刷新頁面。
##### 2. Location 對象
Location 對象包含有關當前 URL 的信息。
**(1)對象屬性:**
屬性 | 描述
---|---
hash | 設置或返回從井號 (#) 開始的 URL(錨)。
host | 設置或返回主機名和當前 URL 的端口號。
hostname | 設置或返回當前 URL 的主機名。
href | 設置或返回完整的 URL。
pathname| 設置或返回當前 URL 的路徑部分。
port | 設置或返回當前 URL 的端口號。
protocol | 設置或返回當前 URL 的協議。
search| 設置或返回從問號 (?) 開始的 URL(查詢部分)。
url 地址解析:
```
function getQueryString (name) {
const reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)', 'i')
const r = window.location.search.substr(1).match(reg)
if (r != null) return (r[2])
return null
}
function createQueryString (data) {
let dataStr = '';
Object.keys(data).forEach(key => {
dataStr += key + '=' + data[key] + '&';
})
dataStr = dataStr.substr(0, dataStr.lastIndexOf('&'));
return dataStr;
}
function parseQueryString () {
let obj = {};
const temp = window.location.search.substr(1).split('&') || [];
for (let item of temp) {
obj[item.split('=')[0]] = item.split('=')[1]
}
return obj;
}
```
**(2)對象方法:**
方法 | 描述
---|---
assign() | 加載新的文檔。
reload() | 重新加載當前文檔。
replace() | 用新的文檔替換當前文檔。
##### 3. Navigator 對象
Navigator 對象包含有關瀏覽器的信息。
**(1)對象屬性:**
屬性 | 描述
---|---
appCodeName | 返回瀏覽器的代碼名。
appMinorVersion | 返回瀏覽器的次級版本。
appName | 返回瀏覽器的名稱。
appVersion | 返回瀏覽器的平臺和版本信息。
browserLanguage | 返回當前瀏覽器的語言。
cookieEnabled | 返回指明瀏覽器中是否啟用 cookie 的布爾值。
cpuClass | 返回瀏覽器系統的 CPU 等級。
onLine | 返回指明系統是否處于脫機模式的布爾值。
platform | 返回運行瀏覽器的操作系統平臺。
systemLanguage| 返回 OS 使用的默認語言。
userAgent | 返回由客戶機發送服務器的 user-agent 頭部的值。
userLanguage | 返回 OS 的自然語言設置。
判斷瀏覽器:
```
function goPage() {
if ((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
window.location.href="你的手機版地址";
}
else {
window.location.href="你的電腦版地址";
}
}
function judgeSystem () {
var value
if (ua.match(/phone|pad|pod|iPhone|iPod|ios|iPad/i)) {
value = 'ios'
} else if (ua.match(/Android/i)) {
value = 'android'
}
return value
}
function isMobile () {
if ((navigator.userAgent.match(/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone)/i))) {
return true
}
else {
return false
}
}
function isWeixin () {
var ua = navigator.userAgent.toLowerCase();
return /micromessenger/i.test(ua) === true;
}
```
**(2)對象方法:**
方法 | 描述
---|---
javaEnabled() | 規定瀏覽器是否啟用 Java。
taintEnabled() | 規定瀏覽器是否啟用數據污點 (data tainting)。
##### 4. Screen 對象
Screen 對象包含有關客戶端顯示屏幕的信息。
**(1)對象屬性:**
屬性 | 描述
---|---
availHeight | 返回顯示屏幕的高度 (除 Windows 任務欄之外)。
availWidth | 返回顯示屏幕的寬度 (除 Windows 任務欄之外)。
width | 返回顯示器屏幕的寬度。
height | 返回顯示器屏幕的高度。
bufferDepth | 設置或返回調色板的比特深度。
colorDepth | 返回目標設備或緩沖器上的調色板的比特深度。
deviceXDPI | 返回顯示屏幕的每英寸水平點數。
deviceYDPI | 返回顯示屏幕的每英寸垂直點數。
fontSmoothingEnabled | 返回用戶是否在顯示控制面板中啟用了字體平滑。
logicalXDPI | 返回顯示屏幕每英寸的水平方向的常規點數。
logicalYDPI | 返回顯示屏幕每英寸的垂直方向的常規點數。
pixelDepth | 返回顯示屏幕的顏色分辨率(比特每像素)。
updateInterval | 設置或返回屏幕的刷新率。
## 二、DOM
### 1、定義
DOM(文檔對象模型)描述了處理網頁內容的方法和接口,是HTML和XML的API,DOM把整個頁面規劃成由節點層級構成的文檔。
### 2、結構
**HTML DOM 樹形結構:**

### 3、DOM對象用法小結
#### (1)查找節點
##### 直接查找:
- document.getElementById()  根據ID獲取一個標簽
- document.getElementsByClassName()  根據class屬性獲取(可以獲取多個元素,所以返回的是一個數組)
- document.getElementsByTagName()  根據標簽名獲取標簽合集
```
<div class="c1" id="d1">
待到將軍歸來日,朕與將軍解戰袍!
</div>
<div class="c1" id="d2">
日照香爐生紫煙,遙看瀑布掛前川!
</div>
var a = document.getElementById('d1'); //獲取id屬性值為d1的標簽 拿到的直接是標簽對象
var b = document.getElementsByClassName('c1'); //獲取class值為c1的所有標簽 拿到的是數組
var c = document.getElementsByTagName('div'); //獲取所有div標簽 拿到的是數組
```
##### 間接查找:
- dom.parentElement  獲取節點標簽的父級標簽
- dom.children  獲取所有子標簽
- dom.firstElementChild  獲取第一個子標簽元素
- dom.lastElementChild  獲取最后一個子標簽元素
- dom.nextElementSibling  獲取下一個兄弟標簽元素
- dom.previousElementSibling  獲取上一個兄弟標簽元素
```
<div class="parent">
<span class="c1" id="d1">
待到將軍歸來日,朕與將軍解戰袍!
</span>
<p class="c1" id="d2">
日照香爐生紫煙,遙看瀑布掛前川!
</p>
</div>
var a = document.getElementById('d1');
var b = document.getElementsByClassName('c1')[0];
var c = document.getElementsByClassName('c1')[1];
var d = document.getElementsByTagName('div')[0];
var p = document.getElementsByClassName('parent')[0];
console.log(a.parentElement.nodeName); // "DIV"
console.log(Array.from(p.children).map(function(v){
return v.nodeName
})); // ["SPAN", "P"]
console.log(d.firstElementChild.nodeName); // "SPAN"
console.log(d.lastElementChild.nodeName); // "P"
console.log(b.nextElementSibling.nodeName); // "P"
console.log(c.previousElementSibling.nodeName); // "SPAN"
```
#### (2)節點操作
- dom.createElement()  創建節點
- dom.appendChild()  在元素末尾插入節點
- dom.insertBefore()   在某個節點之前插入節點
- dom.removeChild()  刪除節點
- dom.replaceChild()  替換節點
```
//動態創建script標簽
function loadScriptString(code) {
var script = document.createElement('script'); //創建一個script標簽
script.type = 'text/javascript';
// script.setAttribute('src', '');
try {
//IE瀏覽器認為script是特殊元素,不能再訪問子節點;報錯;
script.appendChild(document.createTextNode(code));
}
catch (ex) {
script.text = code;
}
document.getElementsByTagName('head')[0].appendChild(script);
}
window.onload = function () {
loadScriptString("alert('Hello World!!!')");
}
```
#### (3)文本操作
- dom.innerText  獲取標簽的文本內容
- dom.innerHTML  獲取標簽內的所有內容,包括文本和標簽
#### (4)屬性操作
- dom.setAttribute()  設置屬性
- dom.getAttribute()  獲取屬性
- dom.removeAttribute()  刪除屬性
#### (5)值操作
- dom.value  獲取值
- dom.value = ' '  設置值
#### (6)class的操作
- dom.classList  獲得這個標簽的class屬性的所有的值
- dom.classList.add()  添加class值
- dom.classList.remove()  刪除class值
- dom.classList.contains()  判斷是否含有有某個class值,有返回true,沒有返回false
- dom.classList.toggle()  切換class,有就刪除,沒有就增加
```
const u = {};
u.isElement = function(obj){
return !!(obj && obj.nodeType == 1);
};
u.hasCls = function(el, cls){
if(!u.isElement(el)){
console.warn('$api.hasCls Function need el param, el param must be DOM Element');
return;
}
if(el.classList.contains(cls)){
return true;
}else{
return false;
}
};
u.addCls = function(el, cls){
if(!u.isElement(el)){
console.warn('$api.addCls Function need el param, el param must be DOM Element');
return;
}
if('classList' in el){
el.classList.add(cls);
}else{
var preCls = el.className;
var newCls = preCls +' '+ cls;
el.className = newCls;
}
return el;
};
u.removeCls = function(el, cls){
if(!u.isElement(el)){
console.warn('$api.removeCls Function need el param, el param must be DOM Element');
return;
}
if('classList' in el){
el.classList.remove(cls);
}else{
var preCls = el.className;
var newCls = preCls.replace(cls, '');
el.className = newCls;
}
return el;
};
u.toggleCls = function(el, cls){
if(!u.isElement(el)){
console.warn('$api.toggleCls Function need el param, el param must be DOM Element');
return;
}
if('classList' in el){
el.classList.toggle(cls);
}else{
if(u.hasCls(el, cls)){
u.removeCls(el, cls);
}else{
u.addCls(el, cls);
}
}
return el;
};
```
#### (7)css操作
- dom.style.backgroundColor
- dom.style.height
注:有橫杠的css屬性,寫法要去掉橫杠,并且橫杠后面的單詞首字母大寫
#### (8)事件
```
onclick 當用戶點擊某個對象時調用的事件句柄。
ondblclick 當用戶雙擊某個對象時調用的事件句柄。
onfocus 元素獲得焦點。 應用場景:輸入框
onblur 元素失去焦點。 應用場景:用于表單驗證,用戶離開某個輸入框時,代表已經輸入完了,我們可以對它進行驗證
onchange 域的內容被改變。 應用場景:通常用于表單元素,當元素內容被改變時觸發(select聯動)
onkeydown 某個鍵盤按鍵被按下。 應用場景: 當用戶在最后一個輸入框按下回車按鍵時,表單提交.
onkeypress 某個鍵盤按鍵被按下并松開。
onkeyup 某個鍵盤按鍵被松開。
onload 一張頁面或一幅圖像完成加載。
onmousedown 鼠標按鈕被按下。
onmousemove 鼠標被移動。
onmouseout 鼠標從某元素移開。
onmouseover 鼠標移到某元素之上。
onselect 在文本框中的文本被選中時發生。
onsubmit 確認按鈕被點擊,使用的對象是form。
```
onblur和onfocus事件
```
<input type="text" id="username" />
var inp = document.getElementById('username');
inp.onfocus = function () {
this.style.backgroundColor = '#f00';
}
inp.onblur = function () {
this.style.backgroundColor = '#00f';
}
```
onchange事件,域內容發生變化時觸發
```
<input type="text" id="username" />
<select name="" id="book">
<option value="1">論語</option>
<option value="2">大學</option>
<option value="3">中庸</option>
<option value="4">孟子</option>
</select>
var inp = document.getElementById('username');
var s = document.getElementById('book');
s.onchange = function () {
inp.value = this.options[this.selectedIndex].innerText;
}
```
- 前言
- 一、css垂直居中的幾種實現方法
- 二、簡單說一下盒模型,說下如何利用BFC解決外邊距重疊的問題
- 三、說一說產生塌陷的原因以及清除浮動的幾種方法
- 四、偽類和偽元素的區別?聊一下css選擇器的優先級
- 五、css中的過渡和動畫效果了解嗎
- 六、彈性盒模型了解嗎
- 七、簡單說下BOM和DOM的區別
- 八、如何解決瀏覽器的兼容性問題?瀏覽器調優都用到過哪些方法
- 九、之前寫過h5嗎?有遇到過哪些兼容性問題?說下怎么解決的
- 十、h5是如何做移動端適配的?折行的時候如何實現不斷行
- 十一、聊一聊js中實現數組拷貝的常用方法
- 十二、聊聊js中的數據類型,如何用js實現一個對象的深拷貝
- 十三、偽數組和數組的區別?相互轉化的方法有哪些
- 十四、請介紹Js中有哪些循環遍歷的方法,關于數組常用的方法有哪些
- 十五、js中的reduce了解嗎?都用他解決過什么問題
- 十六、事件冒泡和捕獲的執行順序了解嗎?什么是事件委托
- 十七、call和apply的區別是什么?caller和callee的區別有哪些
- 十八、javascript中的this都有哪些用法
- 十九、怎么理解js中的原型鏈?如何實現繼承?實現繼承常用的方式有哪些
- 二十、聊一聊js的作用域和作用域鏈
- 二十一、js的閉包了解嗎?閉包的常見用法說一下
- 二十二、setTimeout和setInterval的運行機制了解嗎
- 二十三、函數的柯里化了解嗎?說下函數柯里化應用的場景
- 二十四、用js寫一個ajax的原生實現方法
- 二十五、js如何實現跨域?聊一聊你之前用到過的方法
- 二十六、聊一下cookie、session和token三者的區別及使用
- 二十七、用js實現一下數組去重和排序,有哪些方法可以實現
- 二十八、寫一個方法,統計一下html文檔的元素包括元素的數量
- 二十九、用js實現一個省市級聯效果
- 三十、用js實現一個輪播圖效果,簡單說下原理
- 三十一、請你實現一個大文件上傳和斷點續傳
- 三十二、什么是模塊化開發?談下AMD、CMD、CommonJs和ES6的區別
- 三十三、es6了解嗎?說幾個常見的新特性,set和weakSet的區別是什么
- 三十四、解構賦值的用法了解嗎?如何實現對象和數組的嵌套和重命名
- 三十五、談談你對promise的用法和理解
- 三十六、談談你對es6中的Generator函數的認識
- 三十七、談一下async-await的實現原理
- 三十八、用js實現一下觀察者模式?簡單說一下原理
- 三十九、了解JavaScript中的裝飾器嗎?聊一下JS中的getter與setter的用法
- 四十、聊一下正則表達式里的常見用法