1.1什么是BOM
BOM即瀏覽器對象模型,它提供了獨立于內(nèi)容而與瀏覽器窗口進行交互的對象呈野,其核心對象是window镀赌。
BOM由一系列相關(guān)的對象構(gòu)成,并且每個對象都提供了很多方法與屬性际跪。
BOM缺乏標準,JS語法的標準化組織是ECMA喉钢,DOM的標準化組織是W3C姆打,BOM最初是Netscape瀏覽器標準的一部分。
1.2BOM的構(gòu)成
BOM比DOM更大肠虽,它包含DOM
window對象是瀏覽器的頂級對象幔戏,它具有雙重角色。
1税课、它是JS訪問瀏覽器窗口的一個接口
2闲延、它是一個全局對象。定義在全局作用域中的變量韩玩、函數(shù)都會變成window對象的屬性和方法垒玲。
在調(diào)用的時候可以省略window,前面學習的對話框都屬于window對象方法找颓,如alert()合愈、prompt()等
1.2window的常見事件
1.2.1窗口加載事件
window.onload=function(){}
或者
window.addEventListener("load",function(){});
window.onload是窗口(頁面)加載事件,當文檔內(nèi)容完全加載完成會觸發(fā)該事件(包括圖像击狮、腳本文件佛析、CSS文件等),就調(diào)用的處理函數(shù)彪蓬。
注意:
- 有了window.onload就可以把JS代碼寫道頁面元素的任何地方寸莫,因為onload是等頁面內(nèi)容全部加載完畢,再去執(zhí)行處理函數(shù)档冬。
- window.onload傳統(tǒng)注冊事件方式只能寫一次膘茎,如果有多個,會以最后一個window.onload為準捣郊。
- 如果使用addEventListener則沒有限制
document.addEventListener('DOMContenLoaded',function(){})
DOMContentLoaded事件觸發(fā)時辽狈,僅當DOM加載完成,不包括樣式表呛牲,圖片刮萌,flash等等。i9以上支持娘扩。
如果頁面圖片很多的話着茸,從用戶訪問到onload觸發(fā)可能需要較長的時間壮锻,交互效果就不能實現(xiàn),必然影響用戶體驗涮阔,此時用DOMContentLoaded事件比較合適猜绣。
<script>
// window.onload = function() {
// var btn = document.querySelector('button');
// btn.addEventListener('click', function() {
// alert('點擊我');
// })
// }
// window.onload = function() {
// alert(22);
// }
window.addEventListener('load', function() {
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
alert('點擊我');
})
})
window.addEventListener('load', function() {
alert(22);
})
document.addEventListener('DOMContentLoaded', function() {
alert(33);
})
// load 等頁面內(nèi)容全部加載完畢,包含頁面dom元素 圖片 flash css 等等
// DOMContentLoaded 是DOM 加載完畢敬特,不包含圖片 falsh css 等就可以執(zhí)行 加載速度比 load更快一些
</script>
</head>
<body>
<button>點擊</button>
</body>
1.2.2調(diào)整窗口大小事件
window.onresize = function(){}
window.addEventListener("resize",function(){});
window.onresize是調(diào)節(jié)窗口大小加載事件掰邢,當觸發(fā)時就調(diào)用的處理函數(shù)。
注意:1伟阔、只要窗口大小發(fā)生像素變化辣之,就會觸發(fā)這個事件。
2皱炉、我們經(jīng)常利用這個事件完成響應(yīng)式布局怀估。window.innerWidth當前屏幕的寬度
div {
width: 200px;
height: 200px;
background-color: pink;
}
<script>
window.addEventListener('load', function() {
var div = document.querySelector('div');
window.addEventListener('resize', function() {
console.log(window.innerWidth);
console.log('變化了');
if (window.innerWidth <= 800) {
div.style.display = 'none';
} else {
div.style.display = 'block';
}
})
})
</script>
<div></div>
1.2.3定時器
window對象給我們提供了兩個非常好用的方法-定時器
- setTimeout()
- setInterval()
window.setTimeout(調(diào)用函數(shù),[延遲的毫秒數(shù)]);
setTimeout()方法用于設(shè)置一個定時器,該定時器在定時器到期后執(zhí)行調(diào)用函數(shù)合搅。
setRimeout()這個調(diào)用函數(shù)我們也稱為回調(diào)函數(shù)callback多搀。普通函數(shù)是按照代碼順序直接調(diào)用。而這個函數(shù)灾部,需要等待事件康铭,時間到了才去調(diào)用這個函數(shù),因此稱為回調(diào)函數(shù)梳猪。
注意:1麻削、window可以省略
2、這個調(diào)用函數(shù)可以直接寫函數(shù)春弥,或者寫函數(shù)名呛哟。
3、延遲的毫秒數(shù)省略默認是0匿沛,如果寫扫责,必須是毫秒。
4逃呼、因為定時器可能很多鳖孤,所以我們經(jīng)常給定時器賦值一個標識符。
// 1. setTimeout
// 語法規(guī)范: window.setTimeout(調(diào)用函數(shù), 延時時間);
// 1. 這個window在調(diào)用的時候可以省略
// 2. 這個延時時間單位是毫秒 但是可以省略抡笼,如果省略默認的是0
// 3. 這個調(diào)用函數(shù)可以直接寫函數(shù) 還可以寫 函數(shù)名 還有一個寫法 '函數(shù)名()'
// 4. 頁面中可能有很多的定時器苏揣,我們經(jīng)常給定時器加標識符 (名字)
// setTimeout(function() {
// console.log('時間到了');
// }, 2000);
function callback() {
console.log('爆炸了');
}
var timer1 = setTimeout(callback, 3000);
var timer2 = setTimeout(callback, 5000);
// setTimeout('callback()', 3000); // 我們不提倡這個寫法
1.2.4五秒之后自動關(guān)閉的廣告案例
<img src="images/ad.jpg" alt="" class="ad">
<script>
var ad = document.querySelector('.ad');
setTimeout(function() {
ad.style.display = 'none';
}, 5000);
</script>
1.2.5停止setTimeout()定時器
window.clearTimeout(timeoutID)
<button>點擊停止定時器</button>
<script>
var btn = document.querySelector('button');
var timer = setTimeout(function() {
console.log('爆炸了');
}, 5000);
btn.addEventListener('click', function() {
clearTimeout(timer);
})
</script>
1.2.6setInterval()定時器
window.setInterval(調(diào)用函數(shù),[延遲的毫秒數(shù)]);
setInterval()方法重復(fù)調(diào)用一個函數(shù),每隔這個時間推姻,就去調(diào)用一次回調(diào)函數(shù)平匈。
setInterval(function() {
console.log('繼續(xù)輸出');
}, 1000);
1.2.7倒計時案例
div {
margin: 200px;
}
span {
display: inline-block;
width: 40px;
height: 40px;
background-color: #333;
font-size: 20px;
color: #fff;
text-align: center;
line-height: 40px;
}
<div>
<span class="hour">1</span>
<span class="minute">2</span>
<span class="second">3</span>
</div>
<script>
// 1. 獲取元素
var hour = document.querySelector('.hour'); // 小時的黑色盒子
var minute = document.querySelector('.minute'); // 分鐘的黑色盒子
var second = document.querySelector('.second'); // 秒數(shù)的黑色盒子
var inputTime = +new Date('2019-5-1 18:00:00'); // 返回的是用戶輸入時間總的毫秒數(shù)
countDown(); // 我們先調(diào)用一次這個函數(shù),防止第一次刷新頁面有空白
// 2. 開啟定時器
setInterval(countDown, 1000);
function countDown() {
var nowTime = +new Date(); // 返回的是當前時間總的毫秒數(shù)
var times = (inputTime - nowTime) / 1000; // times是剩余時間總的秒數(shù)
var h = parseInt(times / 60 / 60 % 24); //時
h = h < 10 ? '0' + h : h;
hour.innerHTML = h; // 把剩余的小時給 小時黑色盒子
var m = parseInt(times / 60 % 60); // 分
m = m < 10 ? '0' + m : m;
minute.innerHTML = m;
var s = parseInt(times % 60); // 當前的秒
s = s < 10 ? '0' + s : s;
second.innerHTML = s;
}
</script>
1.2.8停止setInterval()定時器
window.clearInterval(intervalID)
<button class="begin">開啟定時器</button>
<button class="stop">停止定時器</button>
<script>
var begin = document.querySelector('.begin');
var stop = document.querySelector('.stop');
var timer = null; // 全局變量 null是一個空對象
begin.addEventListener('click', function() {
timer = setInterval(function() {
console.log('ni hao ma');
}, 1000);
})
stop.addEventListener('click', function() {
clearInterval(timer);
})
</script>
1.2.9發(fā)送短信的案例
手機號碼: <input type="number"> <button>發(fā)送</button>
<script>
// 按鈕點擊之后,會禁用 disabled 為true
// 同時按鈕里面的內(nèi)容會變化增炭, 注意 button 里面的內(nèi)容通過 innerHTML修改
// 里面秒數(shù)是有變化的忍燥,因此需要用到定時器
// 定義一個變量,在定時器里面隙姿,不斷遞減
// 如果變量為0 說明到了時間梅垄,我們需要停止定時器,并且復(fù)原按鈕初始狀態(tài)
var btn = document.querySelector('button');
var time = 3; // 定義剩下的秒數(shù)
btn.addEventListener('click', function() {
btn.disabled = true;
var timer = setInterval(function() {
if (time == 0) {
// 清除定時器和復(fù)原按鈕
clearInterval(timer);
btn.disabled = false;
btn.innerHTML = '發(fā)送';
} else {
btn.innerHTML = '還剩下' + time + '秒';
time--;
}
}, 1000);
})
</script>
1.3this指向問題
this 指向問題 一般情況下this的最終指向的是那個調(diào)用它的對象
- 全局作用域或者普通函數(shù)中this指向全局對象window( 注意定時器里面的this指向window)
- 方法調(diào)用中誰調(diào)用this指向誰
- 構(gòu)造函數(shù)中this指向構(gòu)造函數(shù)的實例
<button>點擊</button>
<script>
// this 指向問題 一般情況下this的最終指向的是那個調(diào)用它的對象
// 1. 全局作用域或者普通函數(shù)中this指向全局對象window( 注意定時器里面的this指向window)
console.log(this);
function fn() {
console.log(this);
}
window.fn();
window.setTimeout(function() {
console.log(this);
}, 1000);
// 2. 方法調(diào)用中誰調(diào)用this指向誰
var o = {
sayHi: function() {
console.log(this); // this指向的是 o 這個對象
}
}
o.sayHi();
var btn = document.querySelector('button');
// btn.onclick = function() {
// console.log(this); // this指向的是btn這個按鈕對象
// }
btn.addEventListener('click', function() {
console.log(this); // this指向的是btn這個按鈕對象
})
// 3. 構(gòu)造函數(shù)中this指向構(gòu)造函數(shù)的實例
function Fun() {
console.log(this); // this 指向的是fun 實例對象
}
var fun = new Fun();
</script>
1.4JS執(zhí)行機制
JS是單線程
JavaScript語言的一大特點就是單線程输玷,也就是說队丝,同一個時間只能做一件事。這是因為Javascript這門腳本語言誕生的使命所致---javascript是為處理頁面中用戶的交互欲鹏,以及操作DOM而誕生的炭玫。比如我們對某個DOM元素進行添加和刪除操作,不能同時進行貌虾。就應(yīng)該先進行添加,之后再刪除裙犹。
單線程就意味著所有任務(wù)需要排隊尽狠,前一個任務(wù)結(jié)束,才會執(zhí)行下一個任務(wù)叶圃。這樣所導(dǎo)致的問題是:如果JS執(zhí)行時間過長袄膏,這樣就會造成頁面的渲染不連貫,導(dǎo)致頁面渲染加載阻塞的感覺掺冠。
同步和異步
為了解決這個問題沉馆,利用多核cpu的計算能力,HTML5提出Web Worker標準德崭,允許JavaScript腳本創(chuàng)建多個線程斥黑。于是,JS中出現(xiàn)了同步和異步眉厨。
同步
前一個任務(wù)結(jié)束后再執(zhí)行后一個任務(wù)锌奴,程序的執(zhí)行順序與任務(wù)排列順序一致、同步的憾股。比如做飯的同步做法:我們要燒水煮飯鹿蜀,等水開了(10分鐘之后),再去切菜炒菜。
異步
你在做一件事情時服球,因為這件事情會花費很長時間茴恰,在做這件事的同時,你還可以去處理其他事情斩熊。比如做飯的異步做法往枣,我們在燒水的同時娱挨,利用這10分鐘去切菜炒菜粗梭。
同步任務(wù)
同步任務(wù)都在主線程上執(zhí)行,形成一個執(zhí)行棧。
異步任務(wù)
JS的異步是通過回調(diào)函數(shù)實現(xiàn)的扛点,
一般而言,異步任務(wù)有以下三種類型:
1狮辽、普通事件烁巫,如click、resize等
2蘑秽、資源加載饺著,如load、error等
3肠牲、定時器幼衰,包括setInterval、setTimeout等
異步任務(wù)相關(guān)回調(diào)函數(shù)添加到任務(wù)隊列中(任務(wù)隊列也稱為消息隊列缀雳。
JS執(zhí)行機制
1渡嚣、先執(zhí)行執(zhí)行棧中的同步任務(wù)。
2肥印、異步任務(wù)(回調(diào)函數(shù))放入任務(wù)隊列中识椰。
3、一旦執(zhí)行棧中的所有同步任務(wù)執(zhí)行完畢深碱,系統(tǒng)會按次序讀取任務(wù)隊列中的異步任務(wù)腹鹉,于是被讀取的異步任務(wù)結(jié)束等待狀態(tài),進入執(zhí)行棧敷硅,開始執(zhí)行功咒。
輸出結(jié)果:不點擊 123
點擊 123 click*點擊次數(shù)
由于主線程不斷的重復(fù)獲得任務(wù)、執(zhí)行任務(wù)绞蹦、再獲得任務(wù)力奋、再執(zhí)行,所以這種機制被稱為事件循環(huán)(event loop)
1.5location對象
window對象給我們提供了一個location屬性用于獲取或設(shè)置窗體的URL幽七,并且可以用于解析URL刊侯。因為這個屬性返回的是一個對象,所以我們將這個屬性也稱為location屬性
1.5.1URL
統(tǒng)一資源定位符(Uniform Resource Locator锉走,URL)是互聯(lián)網(wǎng)上標準資源的地址滨彻。互聯(lián)網(wǎng)上的每個文件都有唯一URL挪蹭,它包含的信息指出文件的位置以及瀏覽器應(yīng)該怎么處理它亭饵。
URL的一般語法格式為:
1.5.2location對象的屬性
重點記住href和search
1.5.3 5秒之后自動跳轉(zhuǎn)頁面案例
<button>點擊</button>
<div></div>
<script>
var btn = document.querySelector('button');
var div = document.querySelector('div');
btn.addEventListener('click', function() {
// console.log(location.href);
location.;
})
var timer = 5;
setInterval(function() {
if (timer == 0) {
location.;
} else {
div.innerHTML = '您將在' + timer + '秒鐘之后跳轉(zhuǎn)到首頁';
timer--;
}
}, 1000);
</script>
1.5.4 獲取URL參數(shù)案例
index.html
<div></div>
<script>
console.log(location.search); // ?uname=andy
// 1.先去掉? substr('起始的位置'梁厉,截取幾個字符);
var params = location.search.substr(1); // uname=andy
console.log(params);
// 2. 利用=把字符串分割為數(shù)組 split('=');
var arr = params.split('=');
console.log(arr); // ["uname", "ANDY"]
var div = document.querySelector('div');
// 3.把數(shù)據(jù)寫入div中
div.innerHTML = arr[1] + '歡迎您';
</script>
login.html
<form action="index.html">
用戶名: <input type="text" name="uname">
<input type="submit" value="登錄">
</form>
1.5.5location對象的方法
location.assign 記錄瀏覽歷史辜羊,所以可以實現(xiàn)后退功能
location.replace 不記錄瀏覽歷史踏兜,所以不可以實現(xiàn)后退功能。
<button>點擊</button>
<script>
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
// 記錄瀏覽歷史八秃,所以可以實現(xiàn)后退功能
// location.assign('http://www.itcast.cn');
// 不記錄瀏覽歷史碱妆,所以不可以實現(xiàn)后退功能
// location.replace('http://www.itcast.cn');
location.reload(true);
})
</script>
1.6 navigator對象
navigator對象包含有關(guān)瀏覽器的信息,它有很多屬性昔驱,我們最常用的是userAgent疹尾,該屬性可以返回由客戶機發(fā)送服務(wù)器的user-agent頭部的值。
下面前端代碼可以判斷用戶哪個終端打開頁面骤肛,實現(xiàn)跳轉(zhuǎn)纳本。
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=""; //電腦}
1.7 history對象
window對象給我們提供了一個history對象,與瀏覽器歷史記錄進行交互腋颠。該對象包含用戶(在瀏覽器窗口中)訪問過的URL繁成。
index.html
<a href="list.html">點擊我去往列表頁</a>
<button>前進</button>
<script>
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
// history.forward();
history.go(1);
})
</script>
list.html
<a href="index.html">點擊我去往首頁</a>
<button>后退</button>
<script>
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
// history.back();
history.go(-1);
})
</script>