前端筆記 — JS

一. 函數(shù)

函數(shù)名實際上是一個指向函數(shù)對象的指針

  1. 聲明函數(shù)的幾種方式

自定義函數(shù)(函數(shù)聲明)

function fun() {
     //函數(shù)的實現(xiàn)
}
fun(); //調(diào)用函數(shù)

函數(shù)直接量聲明(函數(shù)表達式)

var fun = function() {
     //函數(shù)實現(xiàn)
}
fun(); //調(diào)用函數(shù)

使用對象聲明函數(shù)

var fun = new Function("函數(shù)的實現(xiàn)");
fun(); //調(diào)用函數(shù)
  1. 代碼運行時,解析器會率先讀取函數(shù)聲明,并使其在執(zhí)行任何代碼之前可用,至于函數(shù)表達式,必須等到解析器執(zhí)行到它所在的代碼行,才會真正被解釋執(zhí)行
  1. 執(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)境的變量對象
  1. 其他
     在函數(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ù)組,arguments.length可以獲取實參的個數(shù)
     函數(shù)內(nèi)部arguments.callee代表函數(shù)本身

二. DOM

DOM:document object model 文檔對象模型

  1. 節(jié)點(node)
    標簽是節(jié)點,元素是節(jié)點,屬性是節(jié)點,文字是節(jié)點,一切皆節(jié)點
節(jié)點類型 nodeType nodeName nodeValue 創(chuàng)建方法
文檔(Document) 9 #document null
元素節(jié)點(Element) 1 元素標簽名稱 null createElement
文本節(jié)點(Text) 3 #text 文本的內(nèi)容 createTextNode
注釋節(jié)點(Comment) 8 #comment 注釋的內(nèi)容 createComment
文檔類型(DocumentType) 10 docType名稱 null 不能動態(tài)創(chuàng)建,通過document.doctype獲取
特性節(jié)點(Attr) 2 特性的名稱 特性的值 createAttribute
文檔片段(DocumentFragment) 11 #document-fragment null createDocumentFragment
  1. 獲取元素節(jié)點
    getElementById:通過id獲取對應(yīng)的元素,是唯一的
    getElementsByTagName:通過標簽名獲取所有同種標簽
    getElementsByClassName:通過類名獲取所有同類元素
    querySelector:通過css選擇符,獲取匹配的第一個元素
    querySelectorAll:通過css選擇符,獲取匹配的所有元素
    matchesSelector:判斷調(diào)用元素是否與傳入的css選擇符匹配

  2. 其他獲取節(jié)點的方式

<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é)點box
box1.childElementCount:返回子元素的個數(shù)
box1.nextSibling:下一個兄弟節(jié)點,box1與3號div之間的換行
box1.nextElementSibling:下一個兄弟元素節(jié)點,3號div
box1.previousSibling:上一個兄弟節(jié)點,box1與1號div之間的換行
box1.previousElementSibling:上一個兄弟元素節(jié)點,1號div
box1.firstChild:第一個子節(jié)點,1號span前面的換行
box1.firstElementChild:第一個子元素節(jié)點,1號span
box1.lastChild:最后一個子節(jié)點,3號span后面的換行
box1.lastElementChild:最后一個子元素節(jié)點,3號span
box1.childNodes:所有的子節(jié)點,4個換行加3個span(共7個),可以通過nodeType來判斷是否為元素節(jié)點,元素節(jié)點為1
box1.children:獲取所有的子元素節(jié)點,3個span
  1. 節(jié)點操作
    創(chuàng)建節(jié)點 createElement()
var box1 = document.createElement('div');

添加節(jié)點,添加的都是子節(jié)點
appendChild('節(jié)點') 添加節(jié)點到元素的最后面
insertBefore('新節(jié)點', '參考節(jié)點') 添加節(jié)點到參考節(jié)點的前面
insertBefore('新節(jié)點', null)等價于appendChild()

var box = document.getElementById('box');
box.appendChild(box1);

刪除節(jié)點 removeChild()

box.removeChild(box1);

克隆節(jié)點 cloneNode()

box.cloneNode(); //只克隆box節(jié)點
box.cloneNode(true); //克隆box及內(nèi)部所有節(jié)點

某個節(jié)點是否是另一個節(jié)點的后代contains()

box.contains(p) // 節(jié)點p是否是節(jié)點box的后代
  1. 節(jié)點特性
    獲取特性 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)
}
  1. 文本節(jié)點操作
  • appendData:將text添加到節(jié)點的末尾
  • deleteData(offset, count):從offset位置開始刪除count個字符
  • insetData(offset, text):在offset位置插入text
  • replaceData(offset, count, text):用text替換從offset位置開始到offset+count為止處的文本
  • splitText(offset):從offset位置將當(dāng)前的文本節(jié)點分成兩個文本節(jié)點
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為止處的字符串
  1. normalize()
    一般情況下, 每個元素只有一個文本子節(jié)點,某些情況下可能包含多個文本子節(jié)點,可以使用normalize()方法將所有的文本節(jié)點合并成一個
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!
  1. 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)
  1. 通過classList屬性操作類名
    add(value):添加類名
    contains(value):類名列表是否包含該類名
    remove(value):從類名列表中刪除指定類名
    toggle(value):如果類名列表中有該類名,則刪除,否則添加

  2. 焦點管理
    通過document.activeElement屬性可以獲取DOM中當(dāng)前獲得焦點的元素
    通過document.hasFocus()方法可以用于確定文檔是否獲得了焦點

  3. 插入標記
    innerHTML:讀模式下返回調(diào)用元素所有的子節(jié)點,寫模式下其值會被解析為DOM子樹,替換調(diào)用元素原來的所有子節(jié)點
    outerHTML:讀模式下返回調(diào)用元素本身及所有的子節(jié)點,寫模式下其值會創(chuàng)建新的DOM子樹并替換整個調(diào)用元素
    insertAdjacentHTML():插入標記,接受兩個參數(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代碼中的縮進
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)先(從上至下,從左往右)的遍歷操作

  1. NodeIterator
    使用document.createNodeIterator()方法創(chuàng)建,接受4個參數(shù)
  • root:想要作為遍歷起點的節(jié)點
  • whatToShow:遍歷節(jié)點的過濾類型,常用的有以下幾種
     1.NodeFilter.SHOW_ALL:顯示所有類型的節(jié)點
     2.NodeFilter.SHOW_ELEMENT:顯示元素節(jié)點
     3.NodeFilter.SHOW_TEXT:顯示文本節(jié)點
     4.NodeFilter.SHOW_ATTRIBUTE:顯示屬性節(jié)點
  • filter:節(jié)點過濾的函數(shù),如果應(yīng)該訪問給定的節(jié)點,則返回NodeFilter.FILTER_ACCEPT,否則返回NodeFilter.FILTER_SKIP。沒有過濾函數(shù)傳null
  • entityReferenceExpansion:是否擴展實體引用,在HTML頁面中沒有用

NodeIterator類型的主要方法是nextNode()(不過濾的情況下,該方法返回的是起點節(jié)點)和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()
}
  1. TreeWalker
    使用document.createTreeWalker()方法創(chuàng)建,接受與createNodeIterator相同的4個參數(shù),從起點節(jié)點的第一個子節(jié)點開始。除了包括nextNode()(不過濾的情況下,該方法返回的是起點節(jié)點的第一個子節(jié)點)和previousNode()方法外,還提供下列方法
  • parentNode():遍歷到當(dāng)前節(jié)點的父節(jié)點
  • firstChild():遍歷到當(dāng)前節(jié)點的第一個子節(jié)點
  • lastChild():遍歷到當(dāng)前節(jié)點的最后一個子節(jié)點
  • nextSibling():遍歷到當(dāng)前節(jié)點的下一個同輩節(jié)點
  • previousSibling():遍歷到當(dāng)前節(jié)點的上一個同輩節(jié)點

參數(shù)filter函數(shù)返回的值有所不同,除了NodeFilter.FILTER_ACCEPT與NodeFilter.FILTER_SKIP外,還可以使用NodeFilter.FILTER_REJECT。區(qū)別是FILTER_SKIP跳過相應(yīng)節(jié)點繼續(xù)前進到下一個節(jié)點,F(xiàn)ILTER_REJECT會跳過相應(yīng)節(jié)點及子節(jié)點
 上面的例子中,如果使用TreeWalker遍歷,且filter返回值改為NodeFilter.FILTER_REJECT,則不會有任何結(jié)果,因為ul及其子節(jié)點都會被跳過
 該類型還有一個屬性為currentNode,表示遍歷到的當(dāng)前元素,修改該值,可以修改遍歷的起點

四. offset

通過offset可以獲取元素尺寸,offset屬性是只讀的,只能獲取值,不能賦值

  1. offsetWidth,offsetHeight
    offsetWidth:元素的寬度,offsetHeight:元素的高度
    offsetWidth = width + padding + border
    offsetWidth = height + padding + border

  2. offsetTop,offsetLeft
    offsetTop:元素到已定位父級元素上邊的距離
    offsetleft:元素到已定位父級元素左邊的距離
    從父級的padding開始算,border不算,也就是到父級元素邊框的距離
    如果父級都沒有定位,則以頂級元素(一般為html)為準

  3. offsetParent
    返回最近的已定位的父級元素
    與parentNode的區(qū)別:parentNode獲取的是父元素,無論是否定位,offsetParent是獲取已定位的父級元素,如果都沒有定位,則結(jié)果為body

  4. offsetTop與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可以獲取到元素滾動的尺寸

  1. scrollTop,scrollLeft
    scrollTop:向上滾動的距離
    scrollLeft:向左滾動的距離

  2. 獲取網(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;
  1. scrollTo(x, y)
    滾動內(nèi)容到指定的位置

  2. scrollWidth,scrollHeight
    如果盒子的內(nèi)容沒有超過盒子,則為盒子的寬高(不包括border),否則為內(nèi)容的寬高(包括padding)

六. client

通過client可以獲取元素的可視區(qū)域

  1. clientWidth,clientHeight
    元素可視區(qū)域的寬度,包括padding,不包括border
    可理解為不含border的offsetWidth與offsetHeight

  2. clientTop,clientLeft
    clientTop:上邊框的寬度
    clientLeft:左邊框的寬度

  3. client與offset、scroll的區(qū)別

七. 其他

  1. HTML基本結(jié)構(gòu)訪問方法
    文檔:document
    body:document.body
    title:document.title
    head:document.head
    html:document.documentElement

  2. 檢測窗口區(qū)域
    window.innerWidth,window.innerHeight:窗口的寬高
    document.documentElement.clientWidth:窗口的寬高,不包括滾動條寬高
    document.body.clientWidth:body的寬高,包括padding,不包括border
    window.screen.width,window.screen.height:屏幕的分辨率

  3. 事件冒泡
    當(dāng)一個元素上的事件被觸發(fā)的時候,該元素的所有祖先元素都會觸發(fā)此事件
    不是所有的事件都能冒泡,以下事件不能冒泡:blur、focus、load、unload
    阻止冒泡的方法:
    一般瀏覽器event.stopPropagation()
    ie瀏覽器event.cancelBubble = true

  4. 選中文字
    獲取選中的文字:
    一般瀏覽器:window.getSelection().toString()
    ie:document.selection.createRange().text
    取消選中:
    一般瀏覽器:window.getSelection().removeAllRanges()
    ie瀏覽器:document.selection.empty()

  5. 各種坐標
    pageX、pageY:相對于頂級元素
    clientX、clientY:相對于瀏覽器窗口
    screenX、screenY:相對于屏幕
    offsetX、offsetY:相對于觸發(fā)事件的元素
    layerX、layerY:如果觸發(fā)事件的元素有定位或者overflow不為visible,則相對于該元素,否則相對于已定位或overflow不為visible的父元素,若沒有,相對于頂級元素

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容