一. 函數(shù)
函數(shù)名實(shí)際上是一個指向函數(shù)對象的指針
- 聲明函數(shù)的幾種方式
自定義函數(shù)(函數(shù)聲明)
function fun() {
//函數(shù)的實(shí)現(xiàn)
}
fun(); //調(diào)用函數(shù)
函數(shù)直接量聲明(函數(shù)表達(dá)式)
var fun = function() {
//函數(shù)實(shí)現(xiàn)
}
fun(); //調(diào)用函數(shù)
使用對象聲明函數(shù)
var fun = new Function("函數(shù)的實(shí)現(xiàn)");
fun(); //調(diào)用函數(shù)
- 代碼運(yùn)行時机杜,解析器會率先讀取函數(shù)聲明鹰服,并使其在執(zhí)行任何代碼之前可用,至于函數(shù)表達(dá)式嗦玖,必須等到解析器執(zhí)行到它所在的代碼行较雕,才會真正被解釋執(zhí)行
- 執(zhí)行環(huán)境與作用域鏈
執(zhí)行環(huán)境定義了變量或者函數(shù)有權(quán)訪問的其他數(shù)據(jù)随常,每個執(zhí)行環(huán)境都有一個與之相關(guān)聯(lián)的變量對象掩蛤,環(huán)境中定義的所有變量和函數(shù)都保存在這個對象中
每個函數(shù)都有自己的執(zhí)行環(huán)境,全局執(zhí)行環(huán)境是最外圍的一個執(zhí)行環(huán)境干花,當(dāng)執(zhí)行某個函數(shù)時妄帘,函數(shù)的環(huán)境就會被推入一個環(huán)境棧中,函數(shù)執(zhí)行完后池凄,環(huán)境就會出棧
當(dāng)代碼在一個環(huán)境中執(zhí)行時抡驼,會創(chuàng)建變量對象的一個作用域鏈,并賦值給執(zhí)行環(huán)境的一個特殊的內(nèi)部屬性(即[[Scope]])
作用域鏈的本質(zhì)是一個指向變量對象的指針列表
作用域鏈的用途是保證對執(zhí)行環(huán)境有權(quán)訪問的變量和函數(shù)的有序訪問肿仑,作用域鏈的前端始終是當(dāng)前執(zhí)行環(huán)境的變量對象致盟,下一個變量對象來自包含環(huán)境,末端始終是全局執(zhí)行環(huán)境的變量對象
- 其他
在函數(shù)內(nèi)部使用this關(guān)鍵字表示函數(shù)的調(diào)用者
使用函數(shù)名.length可獲得函數(shù)形參的個數(shù)尤慰,函數(shù)名.caller指向調(diào)用該函數(shù)的函數(shù)馏锡,如果是在全局調(diào)用,則為null
函數(shù)內(nèi)部arguments是一個存放函數(shù)實(shí)參的數(shù)組伟端,arguments.length可以獲取實(shí)參的個數(shù)
函數(shù)內(nèi)部arguments.callee代表函數(shù)本身
二. DOM
DOM:document object model 文檔對象模型
- 節(jié)點(diǎn)(node)
標(biāo)簽是節(jié)點(diǎn)杯道,元素是節(jié)點(diǎn),屬性是節(jié)點(diǎn)责蝠,文字是節(jié)點(diǎn)党巾,一切皆節(jié)點(diǎn)
節(jié)點(diǎn)類型 | nodeType | nodeName | nodeValue | 創(chuàng)建方法 |
---|---|---|---|---|
文檔(Document) | 9 | #document | null | |
元素節(jié)點(diǎn)(Element) | 1 | 元素標(biāo)簽名稱 | null | createElement |
文本節(jié)點(diǎn)(Text) | 3 | #text | 文本的內(nèi)容 | createTextNode |
注釋節(jié)點(diǎn)(Comment) | 8 | #comment | 注釋的內(nèi)容 | createComment |
文檔類型(DocumentType) | 10 | docType名稱 | null | 不能動態(tài)創(chuàng)建萎庭,通過document.doctype獲取 |
特性節(jié)點(diǎn)(Attr) | 2 | 特性的名稱 | 特性的值 | createAttribute |
文檔片段(DocumentFragment) | 11 | #document-fragment | null | createDocumentFragment |
獲取元素節(jié)點(diǎn)
getElementById:通過id獲取對應(yīng)的元素,是唯一的
getElementsByTagName:通過標(biāo)簽名獲取所有同種標(biāo)簽
getElementsByClassName:通過類名獲取所有同類元素
querySelector:通過css選擇符齿拂,獲取匹配的第一個元素
querySelectorAll:通過css選擇符擎椰,獲取匹配的所有元素
matchesSelector:判斷調(diào)用元素是否與傳入的css選擇符匹配其他獲取節(jié)點(diǎn)的方式
<div id="box">
<div>1</div>
<div id="box1">
<span>1</span>
<span>2</span>
<span>3</span>
</div>
<div>3</div>
<div>4</div>
<div>5</div>
</div>
box1.parentNode:父節(jié)點(diǎn)box
box1.childElementCount:返回子元素的個數(shù)
box1.nextSibling:下一個兄弟節(jié)點(diǎn),box1與3號div之間的換行
box1.nextElementSibling:下一個兄弟元素節(jié)點(diǎn)创肥,3號div
box1.previousSibling:上一個兄弟節(jié)點(diǎn),box1與1號div之間的換行
box1.previousElementSibling:上一個兄弟元素節(jié)點(diǎn)值朋,1號div
box1.firstChild:第一個子節(jié)點(diǎn)叹侄,1號span前面的換行
box1.firstElementChild:第一個子元素節(jié)點(diǎn),1號span
box1.lastChild:最后一個子節(jié)點(diǎn)昨登,3號span后面的換行
box1.lastElementChild:最后一個子元素節(jié)點(diǎn)趾代,3號span
box1.childNodes:所有的子節(jié)點(diǎn),4個換行加3個span(共7個)丰辣,可以通過nodeType來判斷是否為元素節(jié)點(diǎn)撒强,元素節(jié)點(diǎn)為1
box1.children:獲取所有的子元素節(jié)點(diǎn),3個span
- 節(jié)點(diǎn)操作
創(chuàng)建節(jié)點(diǎn) createElement()
var box1 = document.createElement('div');
添加節(jié)點(diǎn)笙什,添加的都是子節(jié)點(diǎn)
appendChild('節(jié)點(diǎn)') 添加節(jié)點(diǎn)到元素的最后面
insertBefore('新節(jié)點(diǎn)', '參考節(jié)點(diǎn)') 添加節(jié)點(diǎn)到參考節(jié)點(diǎn)的前面
insertBefore('新節(jié)點(diǎn)', null)等價于appendChild()
var box = document.getElementById('box');
box.appendChild(box1);
刪除節(jié)點(diǎn) removeChild()
box.removeChild(box1);
克隆節(jié)點(diǎn) cloneNode()
box.cloneNode(); //只克隆box節(jié)點(diǎn)
box.cloneNode(true); //克隆box及內(nèi)部所有節(jié)點(diǎn)
某個節(jié)點(diǎn)是否是另一個節(jié)點(diǎn)的后代contains()
box.contains(p) // 節(jié)點(diǎn)p是否是節(jié)點(diǎn)box的后代
- 節(jié)點(diǎn)特性
獲取特性 getAttribute(特性名)
var box = document.getElementById('box');
var className = box.getAttribute('class');
設(shè)置特性 setAttribute(特性名飘哨,特性值)
box.setAttribute('class', 'demo');
刪除特性 removeAttribute(特性名)
box.removeAttribute('title'); //box的title特性被刪除
通過attributes屬性遍歷元素的所有特性
for (let attr of box.attributes) {
console.log(attr.nodeName)
console.log(attr.nodeValue)
}
- 文本節(jié)點(diǎn)操作
- appendData:將text添加到節(jié)點(diǎn)的末尾
- deleteData(offset, count):從offset位置開始刪除count個字符
- insetData(offset, text):在offset位置插入text
- replaceData(offset, count, text):用text替換從offset位置開始到offset+count為止處的文本
- splitText(offset):從offset位置將當(dāng)前的文本節(jié)點(diǎn)分成兩個文本節(jié)點(diǎn)
let div = document.createElement('div')
let text = document.createTextNode('hello world!')
div.appendChild(text)
document.body.appendChild(div)
console.log(div.childNodes.length) // 1
console.log(div.firstChild.nodeValue) // hello world!
div.firstChild.splitText(5)
console.log(div.childNodes.length) // 2
console.log(div.firstChild.nodeValue) // hello
- substringData(offset, count):提取從offset位置開始到offset+count為止處的字符串
- normalize()
一般情況下, 每個元素只有一個文本子節(jié)點(diǎn)琐凭,某些情況下可能包含多個文本子節(jié)點(diǎn)芽隆,可以使用normalize()方法將所有的文本節(jié)點(diǎn)合并成一個
let div = document.createElement('div')
let text1 = document.createTextNode('hello ')
div.appendChild(text1)
let text2 = document.createTextNode('world!')
div.appendChild(text2)
document.body.appendChild(div)
console.log(div.childNodes.length) // 2
div.normalize()
console.log(div.childNodes.length) // 1
console.log(div.firstChild.nodeValue) // hello world!
- documentFragment文檔片段
給一個已經(jīng)存在的ul元素中添加3個li元素,如果逐個添加统屈,會導(dǎo)致瀏覽器反復(fù)渲染胚吁,因此可以使用文檔片段一次性添加
let ul = document.getElementById('list') // 文檔中有一個id為‘list’的ul元素
let fragment = document.createDocumentFragment()
for (let i = 0; i < 3; i++) {
let li = document.createElement('li')
li.innerHTML = `item${i}`
fragment.appendChild(li)
}
ul.appendChild(fragment)
通過classList屬性操作類名
add(value):添加類名
contains(value):類名列表是否包含該類名
remove(value):從類名列表中刪除指定類名
toggle(value):如果類名列表中有該類名,則刪除愁憔,否則添加焦點(diǎn)管理
通過document.activeElement屬性可以獲取DOM中當(dāng)前獲得焦點(diǎn)的元素
通過document.hasFocus()方法可以用于確定文檔是否獲得了焦點(diǎn)插入標(biāo)記
innerHTML:讀模式下返回調(diào)用元素所有的子節(jié)點(diǎn)腕扶,寫模式下其值會被解析為DOM子樹,替換調(diào)用元素原來的所有子節(jié)點(diǎn)
outerHTML:讀模式下返回調(diào)用元素本身及所有的子節(jié)點(diǎn)吨掌,寫模式下其值會創(chuàng)建新的DOM子樹并替換整個調(diào)用元素
insertAdjacentHTML():插入標(biāo)記半抱,接受兩個參數(shù),插入的位置和要插入的HTML文本膜宋,第一個參數(shù)必須是下列值之一
beforebegin:在當(dāng)前元素之前插入一個緊鄰的同輩元素
afterbegin:在當(dāng)前元素前端插入一個子元素
beforeend:在當(dāng)前元素末端插入一個子元素
afterend:在當(dāng)前元素之后插入一個緊鄰的同輩元素
innerText:讀模式下返回調(diào)用元素中包含的所有文本內(nèi)容代虾,寫模式下會將其值以文本的形式替換調(diào)用元素的所有子元素
<div id='content'>
<p>This is a <strong>paragraph</strong> with a list following it.</p>
<ul>
<li>Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
<ul/>
</div>
// 對于這個例子中的div元素而言,其innerText屬性返回下列字符串激蹲,由于瀏覽器的不同棉磨,也可能不包含原始HTML代碼中的縮進(jìn)
This is a paragraph with a list following it.
Item 1
Item 2
Item 3
outerText:讀模式下與innerText的結(jié)果相同,但在寫模式下會替換整個調(diào)用元素
三. DOM遍歷
使用NodeIterator和TreeWalker可以對DOM結(jié)構(gòu)執(zhí)行深度優(yōu)先(從上至下学辱,從左往右)的遍歷操作
- NodeIterator
使用document.createNodeIterator()方法創(chuàng)建乘瓤,接受4個參數(shù)
- root:想要作為遍歷起點(diǎn)的節(jié)點(diǎn)
- whatToShow:遍歷節(jié)點(diǎn)的過濾類型环形,常用的有以下幾種
1.NodeFilter.SHOW_ALL:顯示所有類型的節(jié)點(diǎn)
2.NodeFilter.SHOW_ELEMENT:顯示元素節(jié)點(diǎn)
3.NodeFilter.SHOW_TEXT:顯示文本節(jié)點(diǎn)
4.NodeFilter.SHOW_ATTRIBUTE:顯示屬性節(jié)點(diǎn) - filter:節(jié)點(diǎn)過濾的函數(shù),如果應(yīng)該訪問給定的節(jié)點(diǎn)衙傀,則返回NodeFilter.FILTER_ACCEPT抬吟,否則返回NodeFilter.FILTER_SKIP。沒有過濾函數(shù)傳null
- entityReferenceExpansion:是否擴(kuò)展實(shí)體引用统抬,在HTML頁面中沒有用
NodeIterator類型的主要方法是nextNode()(不過濾的情況下火本,該方法返回的是起點(diǎn)節(jié)點(diǎn))和previousNode()
<div id='div1'>
<p>Hello world!</p>
<ul>
<li>List Item 1</li>
<li>List Item 2</li>
<li>List Item 3</li>
</ul>
</div>
// 遍歷li元素
let div = document.getElementById('div1')
let filter = function(node) {
return node.tagName.toLowerCase() === 'li' ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP
}
let iterator = document.createNodeIterator(div, NodeFilter.SHOW_ELEMENT, filter)
let node = iterator.nextNode()
while (node !== null) {
alert(node.tagName)
node = iterator.nextNode()
}
- TreeWalker
使用document.createTreeWalker()方法創(chuàng)建伺糠,接受與createNodeIterator相同的4個參數(shù)鲤嫡,從起點(diǎn)節(jié)點(diǎn)的第一個子節(jié)點(diǎn)開始。除了包括nextNode()(不過濾的情況下仗岖,該方法返回的是起點(diǎn)節(jié)點(diǎn)的第一個子節(jié)點(diǎn))和previousNode()方法外金麸,還提供下列方法
- parentNode():遍歷到當(dāng)前節(jié)點(diǎn)的父節(jié)點(diǎn)
- firstChild():遍歷到當(dāng)前節(jié)點(diǎn)的第一個子節(jié)點(diǎn)
- lastChild():遍歷到當(dāng)前節(jié)點(diǎn)的最后一個子節(jié)點(diǎn)
- nextSibling():遍歷到當(dāng)前節(jié)點(diǎn)的下一個同輩節(jié)點(diǎn)
- previousSibling():遍歷到當(dāng)前節(jié)點(diǎn)的上一個同輩節(jié)點(diǎn)
參數(shù)filter函數(shù)返回的值有所不同擎析,除了NodeFilter.FILTER_ACCEPT與NodeFilter.FILTER_SKIP外,還可以使用NodeFilter.FILTER_REJECT挥下。區(qū)別是FILTER_SKIP跳過相應(yīng)節(jié)點(diǎn)繼續(xù)前進(jìn)到下一個節(jié)點(diǎn)揍魂,F(xiàn)ILTER_REJECT會跳過相應(yīng)節(jié)點(diǎn)及子節(jié)點(diǎn)
上面的例子中,如果使用TreeWalker遍歷棚瘟,且filter返回值改為NodeFilter.FILTER_REJECT现斋,則不會有任何結(jié)果,因?yàn)閡l及其子節(jié)點(diǎn)都會被跳過
該類型還有一個屬性為currentNode偎蘸,表示遍歷到的當(dāng)前元素步责,修改該值,可以修改遍歷的起點(diǎn)
四. offset
通過offset可以獲取元素尺寸禀苦,offset屬性是只讀的蔓肯,只能獲取值,不能賦值
offsetWidth振乏,offsetHeight
offsetWidth:元素的寬度蔗包,offsetHeight:元素的高度
offsetWidth = width + padding + border
offsetWidth = height + padding + borderoffsetTop,offsetLeft
offsetTop:元素到已定位父級元素上邊的距離
offsetleft:元素到已定位父級元素左邊的距離
從父級的padding開始算慧邮,border不算调限,也就是到父級元素邊框的距離
如果父級都沒有定位,則以頂級元素(一般為html)為準(zhǔn)offsetParent
返回最近的已定位的父級元素
與parentNode的區(qū)別:parentNode獲取的是父元素误澳,無論是否定位耻矮,offsetParent是獲取已定位的父級元素,如果都沒有定位忆谓,則結(jié)果為bodyoffsetTop與style.top的區(qū)別
offsetTop只讀裆装,style.top可讀寫
offsetTop是數(shù)值(50),style.top是帶有單位的字符串("50px")
任何元素都有offsetTop,而只有定位的盒子才有style.top
style.top只能得到行內(nèi)樣式哨免,js設(shè)置的樣式都是行內(nèi)樣式
五. scroll
當(dāng)內(nèi)容超出元素茎活,且元素overflow為scroll時,元素可滾動
通過scroll可以獲取到元素滾動的尺寸
scrollTop琢唾,scrollLeft
scrollTop:向上滾動的距離
scrollLeft:向左滾動的距離獲取網(wǎng)頁scrollTop的方法
谷歌及未聲明DTD的瀏覽器:document.body.scrollTop载荔,document.body.scrollLeft
火狐及其他瀏覽器:document.documentElement.scrollTop,document.documentElement.scrollLeft
ie9以上及最新瀏覽器:window.pageYOffset采桃,window.pageXOffset
兼容性寫法
var scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0;
scrollTo(x, y)
滾動內(nèi)容到指定的位置scrollWidth懒熙,scrollHeight
如果盒子的內(nèi)容沒有超過盒子,則為盒子的寬高(不包括border)普办,否則為內(nèi)容的寬高(包括padding)
六. client
通過client可以獲取元素的可視區(qū)域
clientWidth工扎,clientHeight
元素可視區(qū)域的寬度,包括padding泌豆,不包括border
可理解為不含border的offsetWidth與offsetHeightclientTop,clientLeft
clientTop:上邊框的寬度
clientLeft:左邊框的寬度client與offset吏饿、scroll的區(qū)別
七. 其他
HTML基本結(jié)構(gòu)訪問方法
文檔:document
body:document.body
title:document.title
head:document.head
html:document.documentElement檢測窗口區(qū)域
window.innerWidth踪危,window.innerHeight:窗口的寬高
document.documentElement.clientWidth:窗口的寬高,不包括滾動條寬高
document.body.clientWidth:body的寬高猪落,包括padding贞远,不包括border
window.screen.width,window.screen.height:屏幕的分辨率事件冒泡
當(dāng)一個元素上的事件被觸發(fā)的時候笨忌,該元素的所有祖先元素都會觸發(fā)此事件
不是所有的事件都能冒泡蓝仲,以下事件不能冒泡:blur、focus官疲、load袱结、unload
阻止冒泡的方法:
一般瀏覽器event.stopPropagation()
ie瀏覽器event.cancelBubble = true選中文字
獲取選中的文字:
一般瀏覽器:window.getSelection().toString()
ie:document.selection.createRange().text
取消選中:
一般瀏覽器:window.getSelection().removeAllRanges()
ie瀏覽器:document.selection.empty()各種坐標(biāo)
pageX、pageY:相對于頂級元素
clientX途凫、clientY:相對于瀏覽器窗口
screenX垢夹、screenY:相對于屏幕
offsetX、offsetY:相對于觸發(fā)事件的元素
layerX维费、layerY:如果觸發(fā)事件的元素有定位或者overflow不為visible果元,則相對于該元素,否則相對于已定位或overflow不為visible的父元素犀盟,若沒有而晒,相對于頂級元素