前端笔记 — JS

一. 函数

函数名实际上是一个指向函数对象的指针

  1. 声明函数的几种方式

自定义函数(函数声明)

function fun() {
     //函数的实现
}
fun(); //调用函数

函数直接量声明(函数表达式)

var fun = function() {
     //函数实现
}
fun(); //调用函数

使用对象声明函数

var fun = new Function("函数的实现");
fun(); //调用函数
  1. 代码运行时,解析器会率先读取函数声明,并使其在执行任何代码之前可用,至于函数表达式,必须等到解析器执行到它所在的代码行,才会真正被解释执行
  1. 执行环境与作用域链
     执行环境定义了变量或者函数有权访问的其他数据,每个执行环境都有一个与之相关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中
     每个函数都有自己的执行环境,全局执行环境是最外围的一个执行环境,当执行某个函数时,函数的环境就会被推入一个环境栈中,函数执行完后,环境就会出栈
     当代码在一个环境中执行时,会创建变量对象的一个作用域链,并赋值给执行环境的一个特殊的内部属性(即[[Scope]])
     作用域链的本质是一个指向变量对象的指针列表
     作用域链的用途是保证对执行环境有权访问的变量和函数的有序访问,作用域链的前端始终是当前执行环境的变量对象,下一个变量对象来自包含环境,末端始终是全局执行环境的变量对象
  1. 其他
     在函数内部使用this关键字表示函数的调用者
     使用函数名.length可获得函数形参的个数,函数名.caller指向调用该函数的函数,如果是在全局调用,则为null
     函数内部arguments是一个存放函数实参的数组,arguments.length可以获取实参的个数
     函数内部arguments.callee代表函数本身

二. DOM

DOM:document object model 文档对象模型

  1. 节点(node)
    标签是节点,元素是节点,属性是节点,文字是节点,一切皆节点
节点类型 nodeType nodeName nodeValue 创建方法
文档(Document) 9 #document null
元素节点(Element) 1 元素标签名称 null createElement
文本节点(Text) 3 #text 文本的内容 createTextNode
注释节点(Comment) 8 #comment 注释的内容 createComment
文档类型(DocumentType) 10 docType名称 null 不能动态创建,通过document.doctype获取
特性节点(Attr) 2 特性的名称 特性的值 createAttribute
文档片段(DocumentFragment) 11 #document-fragment null createDocumentFragment
  1. 获取元素节点
    getElementById:通过id获取对应的元素,是唯一的
    getElementsByTagName:通过标签名获取所有同种标签
    getElementsByClassName:通过类名获取所有同类元素
    querySelector:通过css选择符,获取匹配的第一个元素
    querySelectorAll:通过css选择符,获取匹配的所有元素
    matchesSelector:判断调用元素是否与传入的css选择符匹配

  2. 其他获取节点的方式

<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:父节点box
box1.childElementCount:返回子元素的个数
box1.nextSibling:下一个兄弟节点,box1与3号div之间的换行
box1.nextElementSibling:下一个兄弟元素节点,3号div
box1.previousSibling:上一个兄弟节点,box1与1号div之间的换行
box1.previousElementSibling:上一个兄弟元素节点,1号div
box1.firstChild:第一个子节点,1号span前面的换行
box1.firstElementChild:第一个子元素节点,1号span
box1.lastChild:最后一个子节点,3号span后面的换行
box1.lastElementChild:最后一个子元素节点,3号span
box1.childNodes:所有的子节点,4个换行加3个span(共7个),可以通过nodeType来判断是否为元素节点,元素节点为1
box1.children:获取所有的子元素节点,3个span
  1. 节点操作
    创建节点 createElement()
var box1 = document.createElement('div');

添加节点,添加的都是子节点
appendChild('节点') 添加节点到元素的最后面
insertBefore('新节点', '参考节点') 添加节点到参考节点的前面
insertBefore('新节点', null)等价于appendChild()

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

删除节点 removeChild()

box.removeChild(box1);

克隆节点 cloneNode()

box.cloneNode(); //只克隆box节点
box.cloneNode(true); //克隆box及内部所有节点

某个节点是否是另一个节点的后代contains()

box.contains(p) // 节点p是否是节点box的后代
  1. 节点特性
    获取特性 getAttribute(特性名)
var box = document.getElementById('box');
var className = box.getAttribute('class');

设置特性 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. 文本节点操作
  • appendData:将text添加到节点的末尾
  • deleteData(offset, count):从offset位置开始删除count个字符
  • insetData(offset, text):在offset位置插入text
  • replaceData(offset, count, text):用text替换从offset位置开始到offset+count为止处的文本
  • splitText(offset):从offset位置将当前的文本节点分成两个文本节点
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()
    一般情况下, 每个元素只有一个文本子节点,某些情况下可能包含多个文本子节点,可以使用normalize()方法将所有的文本节点合并成一个
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文档片段
    给一个已经存在的ul元素中添加3个li元素,如果逐个添加,会导致浏览器反复渲染,因此可以使用文档片段一次性添加
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中当前获得焦点的元素
    通过document.hasFocus()方法可以用于确定文档是否获得了焦点

  3. 插入标记
    innerHTML:读模式下返回调用元素所有的子节点,写模式下其值会被解析为DOM子树,替换调用元素原来的所有子节点
    outerHTML:读模式下返回调用元素本身及所有的子节点,写模式下其值会创建新的DOM子树并替换整个调用元素
    insertAdjacentHTML():插入标记,接受两个参数,插入的位置和要插入的HTML文本,第一个参数必须是下列值之一
      beforebegin:在当前元素之前插入一个紧邻的同辈元素
      afterbegin:在当前元素前端插入一个子元素
      beforeend:在当前元素末端插入一个子元素
      afterend:在当前元素之后插入一个紧邻的同辈元素
    innerText:读模式下返回调用元素中包含的所有文本内容,写模式下会将其值以文本的形式替换调用元素的所有子元素

<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的结果相同,但在写模式下会替换整个调用元素

三. DOM遍历

使用NodeIterator和TreeWalker可以对DOM结构执行深度优先(从上至下,从左往右)的遍历操作

  1. NodeIterator
    使用document.createNodeIterator()方法创建,接受4个参数
  • root:想要作为遍历起点的节点
  • whatToShow:遍历节点的过滤类型,常用的有以下几种
     1.NodeFilter.SHOW_ALL:显示所有类型的节点
     2.NodeFilter.SHOW_ELEMENT:显示元素节点
     3.NodeFilter.SHOW_TEXT:显示文本节点
     4.NodeFilter.SHOW_ATTRIBUTE:显示属性节点
  • filter:节点过滤的函数,如果应该访问给定的节点,则返回NodeFilter.FILTER_ACCEPT,否则返回NodeFilter.FILTER_SKIP。没有过滤函数传null
  • entityReferenceExpansion:是否扩展实体引用,在HTML页面中没有用

NodeIterator类型的主要方法是nextNode()(不过滤的情况下,该方法返回的是起点节点)和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()方法创建,接受与createNodeIterator相同的4个参数,从起点节点的第一个子节点开始。除了包括nextNode()(不过滤的情况下,该方法返回的是起点节点的第一个子节点)和previousNode()方法外,还提供下列方法
  • parentNode():遍历到当前节点的父节点
  • firstChild():遍历到当前节点的第一个子节点
  • lastChild():遍历到当前节点的最后一个子节点
  • nextSibling():遍历到当前节点的下一个同辈节点
  • previousSibling():遍历到当前节点的上一个同辈节点

参数filter函数返回的值有所不同,除了NodeFilter.FILTER_ACCEPT与NodeFilter.FILTER_SKIP外,还可以使用NodeFilter.FILTER_REJECT。区别是FILTER_SKIP跳过相应节点继续前进到下一个节点,FILTER_REJECT会跳过相应节点及子节点
 上面的例子中,如果使用TreeWalker遍历,且filter返回值改为NodeFilter.FILTER_REJECT,则不会有任何结果,因为ul及其子节点都会被跳过
 该类型还有一个属性为currentNode,表示遍历到的当前元素,修改该值,可以修改遍历的起点

四. 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的区别:parentNode获取的是父元素,无论是否定位,offsetParent是获取已定位的父级元素,如果都没有定位,则结果为body

  4. offsetTop与style.top的区别
    offsetTop只读,style.top可读写
    offsetTop是数值(50),style.top是带有单位的字符串("50px")
    任何元素都有offsetTop,而只有定位的盒子才有style.top
    style.top只能得到行内样式,js设置的样式都是行内样式

五. scroll

当内容超出元素,且元素overflow为scroll时,元素可滚动
通过scroll可以获取到元素滚动的尺寸

  1. scrollTop,scrollLeft
    scrollTop:向上滚动的距离
    scrollLeft:向左滚动的距离

  2. 获取网页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)
    滚动内容到指定的位置

  2. scrollWidth,scrollHeight
    如果盒子的内容没有超过盒子,则为盒子的宽高(不包括border),否则为内容的宽高(包括padding)

六. client

通过client可以获取元素的可视区域

  1. clientWidth,clientHeight
    元素可视区域的宽度,包括padding,不包括border
    可理解为不含border的offsetWidth与offsetHeight

  2. clientTop,clientLeft
    clientTop:上边框的宽度
    clientLeft:左边框的宽度

  3. client与offset、scroll的区别

七. 其他

  1. HTML基本结构访问方法
    文档:document
    body:document.body
    title:document.title
    head:document.head
    html:document.documentElement

  2. 检测窗口区域
    window.innerWidth,window.innerHeight:窗口的宽高
    document.documentElement.clientWidth:窗口的宽高,不包括滚动条宽高
    document.body.clientWidth:body的宽高,包括padding,不包括border
    window.screen.width,window.screen.height:屏幕的分辨率

  3. 事件冒泡
    当一个元素上的事件被触发的时候,该元素的所有祖先元素都会触发此事件
    不是所有的事件都能冒泡,以下事件不能冒泡: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:相对于触发事件的元素
    layerX、layerY:如果触发事件的元素有定位或者overflow不为visible,则相对于该元素,否则相对于已定位或overflow不为visible的父元素,若没有,相对于顶级元素

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342