我的JS第三周

91 阅读6分钟

DOM:

核心dom:可以操作HTML和XML

HTML DOM:只能操作HTML,不能访问自定义属性

XML DOM:只能操作XML,已淘汰

查找元素

1、关系:父、子、兄弟

2、直接找元素:特性

let elem=document.getElementByXXXX()//返回的是一个动态集合(HTMLcollection)
通过CSS选择器进行查找:
let elem=document.querySelector("任意CSS选择器")
缺点:只能找到第一个元素
let elem=document.querySelectorALL("任意选择器")
优点:找到了是一个集合,没找到是一个空集合
2、查找复杂元素很舒服、方便
3、返回的是一个静态集合(Nodelist

面试题:docunment.getXXX与document.querySelector的对比?

1、后者更适合查找复杂元素

2、前者是一个动态集合,后者是静态集合

静态集合与动态集合的区别?

1、动态:每一个DOM发生变化的时候,都会悄悄地查找一遍页面元素,让页面与数据保持一致,效率降低,且不支持forEach

2、静态:DOM发生变化的时候并不会查找页面,效率提高,且支持forEach

操作样式

1、内联

获取:elem.style.属性名
设置:elem.style.属性名="属性值"

2、样式表:过于麻烦,建议不用

1、获取样式表:
let sheet=document.stylesheet[i]
2、获取所有的样式规则:
let rules=sheet.cssRules
3、数出你要操作的第几个样式:
let rule=rules[i]
4、操作
rule.style.属性名="属性值"

操作属性

1、获取属性值

 核心DOMelem.getAttribute("属性名")
 HTML DOMelem.属性名

2、删除属性:设置为空字符串只是说明属性值被删除了,但是属性名还在,有一些属性并不需要属性值就能够生效(checked/readonly/href)

 核心DOM:elem.removeAttribute("属性名");
 HTML DOM:elem.属性名=""

3、操作内容

innerHTML/innerText/value

4、如何创建元素以及上树

①、创建空标签:

let elem=document.creatElement("标签名")

②、为其设置必要的属性和事件

elem.属性名="属性值"
elem.on事件名=function(){}

③上树:

1、父元素.appendChild(elem)//父元素的末尾加上
2、父元素.insertBefore(elem,已有子元素)//在父元素中的已有子元素之前添加
3、父元素.replaceChild(elem,已有子元素)//替换掉你的已有子元素

删除

elem.remove();

扩展:

1、inuput/textarea的两个专属事件:onfocus(获取焦点)onblur(失去焦点)

2、创建: let变量名=值;

作用:解决了声明提前

②带来了块级作用域;{}就是一个块

③如果使用let当作下标去绑定事件,会记录着你的下标,不需要再自定义下标了,forEach的i也是let创建的

3、类数组对象转为普通数组:

 x=Array.from(类数组)

递归

简单的来说就是在函数中再调用一次自己;

使用:专门用来遍历层级不明确的dom树或者数据的

 function 函数名(root){
    1、第一层做操作,直接做
    2、判断是否有下一层,若是有下一层就再次调用自己,但是传入的实参要变成下一层
}
函数名(根节点)

算法:深度优先算法,优先遍历当前节点的子节点,子节点遍历完之后才会遍历兄弟节点

缺陷:性能相对较差,同时开启了大量的数据调用

递归VS纯循环:

递归较为简单,性能低,纯循环比较难,性能高

2、绑定事件

1、在HTML上直接书写:不推荐

 <elem on事件名=function()></elem>

2、在js中

 elem.on事件名=function(){操作}

优点:①、符合内容与样式的分离

②、动态绑定,一个可绑定多个元素

③、无兼容问题

3、在JS中使用事件API

 主流:elem.addEventListener("事件名",callback)
 老IE:elem.attachEvent("事件名",callback)

优点:①、符合内容与样式的分离

②、动态绑定,一个可绑定多个元素 ③、支持绑定多个函数对象

缺点:兼容问题

扩展:

select&option可简化创建上树

 select.add(new Option("innerHTML","value"))

event(事件对象):

1、事件周期:三个阶段

①捕获阶段:由外向内

②目标优先触发:目标元素->当前点击的实际发生的元素

③冒泡触发:由内向外

2、获取事件对象event:

主流:会自动作为事件处理函数的第一个形参传入e,老IE使用event,兼容使用event

①获取鼠标的位置/坐标:

相对于屏幕的坐标:e.screenX/Y
相对于浏览器:e.clientX/Y
相对于网页:e.page.X/Y

②阻止冒泡

主流:e.stopPropagation
老IE(兼容):e.cancel.Bubble

③事件委托

优化:如果多个子元素绑定了相同/相似的事件,最好只给父元素绑定一次

主流:e.target
老IE(兼容):e.srcElement

④阻止浏览器的默认行为;

主流:e.preventDefault
老IE(兼容):e.returnValue=false

新学的事件:

1、右键事件:window.oncontextmenu;

2、键盘事件:

window.onkeydown---按下和按住任何键都会触发
window.onkeypress---按下或者按住字母数字空格回车触发
window.onkeyup---松开任意键的时候触发

3、获取键盘的键码:

e.keyCode---获取键码,百度查看e.keyCode表

事件的取消绑定: 1、elem.on事件名=()=>{};那么想要取消就要:elem.on事件名=null

2、如果你使用的是elem.addEventListener("事件名",f1),如果要取消就使用:elem.removeEventListener("事件名",f1),事件名和回调函数必须一模一样,f1是调用函数,但是不加()

this的指向:

①单个元素绑定,指代当前元素

②多个元素绑定:当前触发的元素

③箭头函数,指外部对象

④函数中的this->当前正在调用函数的人

⑤定时器:window

ES5强制改变this的指向:

call/apply:临时替代了函数中的this

语法:

1.函数名.call(借用的对象,实参....)-单独传入每个参数

2.函数名.apply(借用的对象,数组)只能传入一个实参数组

强调:call/apply相当于立刻调用函数,会立刻执行

bind:永久的替换了函数中的this

语法

let 新函数名=函数名.bind(指定对象,永久固定的实参)

三件事:

①创建了一个与原函数功能完全相同的新函数

②将新函数的this永久绑定为了指定对象,别人接不走

③将新函数的部分实参永久固定

强调:bind绑定的新函数无法被call/apply借用,不会立刻调用,需要手动调用

固定套路:

1.Math.max/min.apply(Math,数组)
2.类数组->数组
①Array.from(类数组)
②x=Array.protoType.slice.call/apply
3.判断x是不是数组
Object.prototype.toString.call(x)=="[object Array]"true就是一个数组

ES6

1、let

2、const 常量名=值

3、箭头函数:简化一切回调函数

4、模板字符串:可以直接识别变量,不用+再去进行凭借操作

`我的名字叫${name}`

5、解构赋值:解析结构再进行赋值

使用:1、类数组的解构赋值

let[a,b,c]=[1,2,3]

2、类似对象的解构赋值:

let {a,b=默认值,c}={a:1,c:3}

3、调用函数时,传递的实参顺序无所谓

function({形参,...}){}
    函数名({实参,...})=>无所谓顺序

4、函数的返回结果,可以有多个

function f1(){
    let a=1,b=2
    return[a,b]
}
let[a,b]=f1()

5、Set与MAp set可以用来数组去重

[...new Set(arr)]

正则表达式

使用:

最简单的正则就是关键字原文:"no"->/no/
后缀g找全部   i忽略大小写
2、备选字符集:/[备选字符集]/

强调:一个中括号代表一位字符

2、前面加^后面加$,两者同时使用代表从头到尾完全匹配

/^[备选字符集]$/

特殊:如果备选字符集的ASCII码是连续的可以使用-

一位数字:[0-9]
一位字母:[A-Za-z]
一位汉字:[\u4e00-\u9fa5]
除了XXX以外:[^]

3、预定义字符集:

一位数字:\d
一位数字、字母、下划线:\w
一位空白字符:\s
一位除了换行以外的元素:.

建议:优先使用预定义

4、量词:规定一个字符出现的次数:

1/{n,m}至少出现n个,至多出现m个
2/{n,}至少出现n个,上无限制
3/{n}只能出现n个
4/?可有可无,最多一个
5/*可有可无,上限制
6/+至少一个,上无限制

5、选择和分组:

选择:

规则1|规则2

分组:(规则1|规则2)

6.开头^结尾$

7、预判:(?!+$)

(?![0-9]+$)不能全数字
(?![0-9a-z]+$)不能全数字,不能全小写,也不能全数字和小写的组合

2、支持正则的API

一、切割:

let arr=str.splice(RegExp)

二、替换

基础替换:
let newstr str.replace(RegExp,"新内容")
高级替换:
let newstr=str.replace(/reg/,function(key,i,str){
    key是关键字
    i是下标
    str是原文本身
})

三、格式化:

let newwstr=str.replace(reg,function(a,b,c,d){
    若是正则中出现了分组,那么会得到更多的形参,第一个为关键字,第二个形参为第一个分组的内容、倒数第二个是下标,最后一个是原文

})

3、正则对象

1、直接量:
let reg=/正则表达式/后缀
2、构造函数:
let reg=new RegExp("正则表达式","后缀")

API

验证:let bool=reg.test(str);true为成功,false为失败