JS 节点 正则表达式
1. 节点操作
基本概念
复制标签,会使用克隆方法
写入标签时,会使用节点操作方法
什么是节点?
整个的HTML文件,其中的所有内容,都视为HTML文件的一个节点对象
可以通过操作这些节点对象,来操作HTML文件
DOM节点:DOM 就是我们 html 结构中一个一个的节点构成的
不光我们的标签是一个节点,我们写的文本内容也是一个节点,注释,包括空格都是节点
DOM 的节点我们一般分为常用的三大类 元素节点 / 文本节点 / 属性节点
比如我们在获取元素的时候,通过各种方法获取到的我们叫做元素节点(标签节点)
比如我们标签里面写的文字,那么就是文本节点
写在每一个标签上的属性,就是属性节点
起始节点操作,就是另一种 DOM 操作,也是获取对象,操作对象
只是节点操作,比 DOM 操作,更加复杂更加丰富
节点的类型
之前的 DOM 操作,只能获取标签对象
现在的 节点 操作,可以获取标签对象,可以获取内容对象,可以获取属性对象,甚至可以获取注释内容
通过节点,获取的对象,和通过 DOM方法获取的对象,实际上,是相同意义上的对象
关键一点: 不管是 DOM方式 还是 节点方式 获取的标签对象,内容可能不同,形式是完全一致的
DOM方式 获取的标签对象,支持节点操作
节点方式 获取的节点对象,支持DOM操作
只要正确的获取对象,之后想怎么操作,怎么操作
2. 节点操作之获取节点对象
获取DOM节点 | |
---|---|
childNodes: | 获取某一个节点下 所有的子一级节点 |
children : | 获取某一节点下所有的子一级 元素节点 |
firstChild: | 获取某一节点下子一级的 第一个节点 |
lastChild: | 获取某一节点下子一级的 最后一个节点 |
firstElementChild: | 获取某一节点下子一级 第一个元素节点 |
lastElementChild: | 获取某一节点下子一级 最后一个元素节点 |
nextSibling: | 获取某一个节点的 下一个兄弟节点 |
previousSibling: | 获取某一个节点的 上一个兄弟节点 |
nextElementSibling: | 获取某一个节点的 下一个元素节点 |
previousElementSibling: | 获取某一个节点的 上一个元素节点 |
parentNode: | 获取某一个节点的 父节点 |
attributes: | 获取某一个 元素节点 的所有 属性节点 |
节点属性 | |
---|---|
nodeType: | 获取节点的节点类型,用数字表示 |
元素节点:1 属性节点:2 文本节点:3 注释节点:8 | |
nodeName: | 获取节点的节点名称 |
元素节点:标签名称 属性节点:属性名 文本节点:#text 注释节点:#comment | |
nodeValue: | 获取节点的值 |
元素节点:null 属性节点:属性值 文本节点:内容 注释节点:内容 |
操作DOM节点 | |
---|---|
document.createElement() | 创建一个元素节点 |
box.appendChild(node) | 把node节点插入到box的内部最后的位置 |
box.insertBefore(newNode, existNode) | 在box内,把newNode节点插入到exsitNode的前面 |
box.removeChild(node) | 删除box内部的子节点 |
obj.cloneNode() | 克隆obj节点,可以传一个布尔值为参数,如果参数为true,连同obj子元素一起克隆。 |
获取节点对象的方法
var oDiv = document.querySelector(‘div’);
- 获取当前标签中所有的子级节点
执行结果,是一个伪数组,可以forEach()
形式是与 querySelectorAll() 获取的伪数组是一样的
console.log( oDiv.childNodes ); - 获取当前标签中,所有的元素节点/标签节点
执行结果,是一个伪数组,不能forEach()
console.log( oDiv.children ); - 获取当前标签中,第一个节点
执行结果,是一个对象,内容形式与DOM操作方式,获取的内容是一样的
console.dir( oDiv.firstChild ); - 获取当前标签中,最后一个节点
执行结果,是一个对象,内容形式与DOM操作方式,获取的内容是一样的
console.dir( oDiv.lastChild );
console.dir( document.querySelector(‘span’) ); - 获取当前标签中,第一个标签节点,其他节点不会获取
console.log( oDiv.firstElementChild ); - 获取当前标签中,最后一个标签节点,其他节点不会获取
console.log( oDiv.lastElementChild ); - 获取当前标签,上一个兄弟节点(找哥哥)
如果没有执行结果是null
console.log( oDiv.previousSibling ); - 获取当前标签,下一个兄弟节点(找弟弟)
如果没有执行结果是null
console.log( oDiv.nextSibling ); - 获取当前标签,上一个兄弟元素节点(找标签哥哥)
console.log( oDiv.previousElementSibling ); - 获取当前标签,下一个兄弟元素节点(找标签弟弟)
console.log( oDiv.nextElementSibling ); - 获取当前标签,父级节点
只获取直接父级节点
console.log( oDiv.parentNode );
console.log( document.querySelector(‘span’).parentNode ); - 获取当前标签,所有属性节点
执行结果,是一个伪数组,不能forEach()
console.log( oDiv.attributes );
<!-- 我是注释1 -->
<div name="div" index="1" href="aaa" checked>我是标签div
<!-- 我是注释2 -->
<span>我是标签span</span>
</div>
<!-- 我是注释3 -->
<p>我是标签p</p>
<script>
// 获取节点对象的方法
var oDiv = document.querySelector('div');
// 1,获取当前标签中所有的子级节点
// 执行结果,是一个伪数组,可以forEach()
// 形式是与 querySelectorAll() 获取的伪数组是一样的
console.log( oDiv.childNodes );//NodeList(5) [ #text, <!-- 我是注释2 -->, #text, span, #text ]
// 2,获取当前标签中,所有的元素节点/标签节点
// 执行结果,是一个伪数组,不能forEach()
console.log( oDiv.children );//HTMLCollection { 0: span, length: 1 }
// 3,获取当前标签中,第一个节点
// 执行结果,是一个对象,内容形式与DOM操作方式,获取的内容是一样的
console.dir( oDiv.firstChild );//#text "我是标签div "
// 4,获取当前标签中,最后一个节点
// 执行结果,是一个对象,内容形式与DOM操作方式,获取的内容是一样的
console.dir( oDiv.lastChild );//#text " "
console.dir( document.querySelector('span') );//<span>
// 5,获取当前标签中,第一个标签节点,其他节点不会获取
console.log( oDiv.firstElementChild );//<span>
// 6,获取当前标签中,最后一个标签节点,其他节点不会获取
console.log( oDiv.lastElementChild );//<span>
// 7,获取当前标签,上一个兄弟节点(找哥哥)
// 如果没有执行结果是null
console.log( oDiv.previousSibling );//#text " "
// 8,获取当前标签,下一个兄弟节点(找弟弟)
// 如果没有执行结果是null
console.log( oDiv.nextSibling );//#text " "
// 9,获取当前标签,上一个兄弟元素节点(找标签哥哥)
console.log( oDiv.previousElementSibling );//null
// 10,获取当前标签,下一个兄弟元素节点(找标签弟弟)
console.log( oDiv.nextElementSibling );//<p>
// 11,获取当前标签,父级节点
// 只获取直接父级节点
console.log( oDiv.parentNode );//<body>
console.log( document.querySelector('span').parentNode );//<div name="div" index="1" href="aaa" checked="">
// 12,获取当前标签,所有属性节点
// 执行结果,是一个伪数组,不能forEach()
console.log( oDiv.attributes );//NamedNodeMap(4) [ name="div", index="1", href="aaa", checked="" ]
总结
- 通过节点操作获取的对象/伪数组与通过 DOM操作的对象/伪数组,形式上是一致的
可以相互操作,DOM方法可以操作 节点对象
节点方法可以操作 DOM对象 - 执行结果,伪数组/对象
伪数组有的可以forEach, 有的不能forEach
3. 节点操作之类型名称内容
节点的类型,名称,内容 | |
---|---|
节点的类型: | 对象.nodeType 属性中存储,数据是 一个数值 |
元素节点/标签节点 : | 1 |
属性节点 : | 2 |
文本节点 : | 3 |
注释节点 : | 8 |
节点的名称: | 对象.nodeName |
元素节点/标签节点 : | 大写字母的 标签名称 |
属性节点 : | 小写字母的 属性名称 |
文本节点 : | #text |
注释节点 : | #comment |
节点的内容: | 对象.nodeValue |
元素节点/标签节点 : | null |
属性节点 : | 属性的属性值 |
文本节点 : | 文本内容,包括换行和空格 |
注释节点 : | 注释内容,包括换行和空格 |
4. 节点的操作
-
节点的操作
节点的 新增 删除 克隆 写入
(1) 删除节点 删除当前标签中的子级节点
当前标签.removeChild(‘你要删除的节点’)
(2) 克隆节点 克隆复制当前节点对象
只克隆标签本身 当前标签.cloneNode();
克隆标签以及标签内容 当前标签.cloneNode(true);
(3)写入节点
当前标签.appendChild(你要写入的标签对象) 在当前标签结束位置写入
当前标签.insertBefore(你要写入的标签对象 , 在哪个子级标签前) 在当前标签,子级标签之前,写入 一个标签对象,只会出现在最后一次写入的位置
相对对于将一个标签对象,多次写入,从上一个位置,会移动到下一个位置
只会出现在最后一个位置
var d = document.querySelector(‘div’);
d.appendChild(oText);
d.insertBefore(oDiv , d.firstChild);
d.appendChild(oDiv); -
节点的创建
创建标签节点: document.createElement(‘标签名称’);
创建的是一个标签对象
之前是设定字符串,写入HTML文件,浏览器执行为标签效果
创建文本节点: document.createTextNode(‘要创建的文本内容’);
现在创建的是一个对象,要操作标签的内容,属性属性值等,必须要通过对象的方法来设定
var oDiv = document.createElement(‘div’);
使用操作对象的方式,给标签添加设定
oDiv.id = ‘div1’;
setAttribute,来设定自定义属性
oDiv.setAttribute(‘index’ , 1);
console.dir(oDiv); //
var oText = document.createTextNode(‘要创建的文本内容’);
console.log(oText); //#text “要创建的文本内容”
5.正则表达式
什么是正则表达式:
对字符串内容,进行格式和内容的验证
对于正则表达式,我们不用自己去写,所有常用的正则表达式,在网上都可以搜到;我们只需要能看懂,会使用;所有的计算机语言,正则表达式,都是相同的,通用.
正则表达式的基本语法
- 字面量(常用)
使用 // 来包裹表达式内容
var 变量 = /正则表达式/ - 构造函数
var 变量 = RegExt(‘正则表达式’);
正则表达式的使用方法
- 验证
判断字符串内容是否符合正则表达式的规范
执行结果是 布尔类型
语法 : 正则表达式.test(‘字符串内容’); - 捕获
捕获获取字符串中符合正则表达式规范的内容
执行结果是捕获获取到的符合规范的字符串内容
语法 : 正则表达式.exec(‘字符串内容’)
6. 正则表达式的常用语法
正则表达式,常用语法规范
正则表达式中,不要随便写空格,也会作为验证格式的一部分
元字符
使用一些符号,来表示规范
元字符 | |
---|---|
\d | 表示数值,数字, |
\D | 表示非数字, |
\w | 表示数字,字母,下划线 |
\W | 表示非数字,字母,下划线 |
\s | 表示空格 |
\S | 表示非空格 |
. | 表示非换行(字符串中的换行,使用 转义符 \n 表示) |
提示
正则表达式和转义符,都是 \内容的形式 ; JavaScript会自动识别,如果是 \内容 符合正则表达式,就按照正则表达式来执行 ; 符合转义符,就按照转义符的形式执行 ; 正则表达式和转义符不会冲突
// 只要有数字即可,不用都是数字
var reg1 = /\d/ ;
console.log(reg1.test('123456')) ; //true
console.log(reg1.test('abcd')) ; //false
console.log(reg1.test('1234abcd')) ; //true
var reg2 = /\D/;
console.log(reg2.test('123456')) ; //false
console.log(reg2.test('abcd')) ; //true
console.log(reg2.test('1234abcd')) ; //true
var reg3 = /\w/;
console.log( reg3.test('123avbc_') ); //true
console.log( reg3.test('aaa@qq.com#$%^') ); //false
console.log( reg3.test('aaa@qq.com#$%^') ); //true
var reg4 = /\W/;
console.log( reg4.test('123avbc_') ); //false
console.log( reg4.test('aaa@qq.com#$%^') ); //true
console.log( reg4.test('aaa@qq.com#$%^') ); //true
var reg5 = /\s/;
console.log( reg5.test(' ') ); //true
console.log( reg5.test('312斤kfjisa') ); //false
console.log( reg5.test('312斤 kfjisa') ); //true
var reg6 = /\S/;
console.log( reg6.test(' ') ); //false
console.log( reg6.test('312斤kfjisa') ); //true
console.log( reg6.test('312斤 kfjisa') ); //true
var reg7 = /./;
console.log( reg7.test('\n') ); //true
7.限定符号 限定符号
边界符
^ 表示开头
$ 表示结尾
以数字开头即可,之后的内容,不做限定
var reg1 = /^\d/;
console.log(reg1.test('123')); //true
console.log(reg1.test('123abc')); //true
console.log(reg1.test('abc123')); //false
//以数字结尾,就看结尾,之前有什么内容不管
var reg2 = /\d$/;
console.log(reg2.test('123')); //true
console.log(reg2.test('123abc')); //false
console.log(reg2.test('abc123')); //true
// 如果开头结尾都加上了,限定效果就不同了
// 只能有一个字符串,并且这个字符是数字 只能有一个数字字符
// 字符个数,内容,不符合都不行
var reg3 = /^\d$/;
console.log(reg3.test('1')); //true
console.log(reg3.test('-1')); //false
console.log(reg3.test('a')); //false
console.log(reg3.test('123')); //false
console.log(reg3.test('123abc')); //false
console.log(reg3.test('abc123')); //false
console.log(reg3.test('123abc123')); //false
限定符 限定出现次数
一般都要和边界符配合使用,否则执行效果有问题
* | 表示允许的次数是 0 至 正无穷次 有没有都行 |
+ | 表示允许的次数是 1 至 正无穷次 至少有一个 |
? | 表示允许的次数是 0 至 1 最多有一次 |
{n} | 表示允许的次数是 n 次 n的数值,是自定义数值 |
{n,} | 表示允许的次数是 n 次以上,包括n次 最少是n次,多个不管;也就是 n 至 正无穷 次 |
{n,m} | 表示允许的次数是 n 至 m 次 包括n和m |
// 只能是数字字符,字符个数没有要求
var reg4 = /^\d*$/;
console.log( reg4.test('1') ); //true
console.log( reg4.test('') ); //true
console.log( reg4.test('123') ); //true
console.log( reg4.test('123abc') ); //false
console.log( reg4.test('123abc123') ); //false
// 必须是数字字符,至少出现1个数字字符
var reg5 = /^\d+$/;
console.log( reg5.test('1') ); //true
console.log( reg5.test('') ); //false
console.log( reg5.test('123') ); //true
console.log( reg5.test('123abc') ); //false
console.log( reg5.test('123abc123') ); //false
// 必须是数字字符,最多只能有0个或者1个字符
var reg6 = /^\d?$/;
console.log( reg6.test('1') ); //true
console.log( reg6.test('') ); //true
console.log( reg6.test('123') ); //false
console.log( reg6.test('123abc') ); //false
console.log( reg6.test('123abc123') ); //false
// 只能是3个数字字符
var reg7 = /^\d{3}$/;
console.log( reg7.test('1') ); //false
console.log( reg7.test('') ); //false
console.log( reg7.test('123') ); //true
console.log( reg7.test('123abc') ); //false
console.log( reg7.test('123abc123') ); //false
// 必须都是数字字符,并且至少有一个数字字符
var reg8 = /^\d{1,}$/;
console.log( reg8.test('1') ); //true
console.log( reg8.test('') ); //false
console.log( reg8.test('123') ); //true
console.log( reg8.test('123abc') ); //false
console.log( reg8.test('123abc123') ); //false
// 都是数字,1至3次
var reg9 = /^\d{1,3}$/;
console.log( reg9.test('1') ); //true
console.log( reg9.test('') ); //false
console.log( reg9.test('123') ); //true
console.log( reg9.test('123abc') ); //false
console.log( reg9.test('123abc123') ); //false
8.正则表达式之特殊符号
正则表达式的特殊符号
- \ 可以表示正则表达式的规范,或者是转义符
设定是不冲突的,符合哪个就执行哪个 -
| 表示逻辑或的关系
表示两个规范,满足哪个都可以
如果要表示多种内容,并且限定字符个数
公式 : (内容1|内容2|内容3…){次数限定} - ( ) 将( )中的内容作为一个整体,来执行,确保执行正确
- [ ] 在[ ]中设定的内容,任意满足其中一个就可以 abcd
- - 表示在这个范围内的就可以 a-d
- [^内容] 表示 非内容
-
i 忽略大小写
g 全局匹配
必须写在 / / 之外 /正则表达式/i /正则表达式/g
一般是与其他的函数配合使用
逻辑或的判定
- 内容的判断,正常的判断
- 个数的判断,只要是包含个数就可以
//内容,可以是数字,字母,下划线,字符只要是3个就行,不能少,可以多
// 实际上是一种错误的语法形式
// var reg1 = /^\d{3}|\w{3}$/;
// 数字或者数字字符下划线,并且个数只能是三个
// var reg1 = /^(\d|\w){3}$/;
// 也可以
var reg1 = /^\d{3}$|^\w{3}$/;
console.log( reg1.test( '123' ) ); //true
console.log( reg1.test( 'abc' ) ); //true
console.log( reg1.test( '1234' ) ); //false
console.log( reg1.test( 'abcd' ) ); //false
console.log( reg1.test( '1!1' ) ); //false
console.log( reg1.test( 'a&b' ) ); //false
console.log( reg1.test( 'ab' ) ); //false
console.log( reg1.test( '12' ) ); //false
console.log( reg1.test( '12&12' ) ); //false
console.log( reg1.test( 'ab&ab' ) ); //false
// 内容只能是 a b c d 4个字符,多了不可以
var reg2 = /^[abcd]$/;
console.log( reg2.test('a') ); //true
console.log( reg2.test('b') ); //true
console.log( reg2.test('c') ); //true
console.log( reg2.test('d') ); //true
console.log( reg2.test('ab') ); //false
console.log( reg2.test('abc') ); //false
console.log( reg2.test('abcd') ); //false
console.log( reg2.test('bc') ); //false
console.log( reg2.test('bcd') ); //false
console.log( reg2.test('cd') ); //false
// a-d之间的字符,只能是一个
var reg3 = /^[a-d]$/;
console.log( reg3.test('a') ); //true
console.log( reg3.test('b') ); //true
console.log( reg3.test('c') ); //true
console.log( reg3.test('d') ); //true
console.log( reg3.test('ab') ); //false
console.log( reg3.test('abc') ); //false
console.log( reg3.test('abcd') ); //false
console.log( reg3.test('bc') ); //false
console.log( reg3.test('bcd') ); //false
console.log( reg3.test('cd') ); //false
// 字符范围不再 a-d 之间,并且是一个字符
var reg4 = /^[^(a-d)]$/;
console.log( reg4.test('a') ); //false
console.log( reg4.test('b') ); //false
console.log( reg4.test('c') ); //false
console.log( reg4.test('d') ); //false
console.log( reg4.test('ab') ); //false
console.log( reg4.test('abc') ); //false
console.log( reg4.test('abcd') ); //false
console.log( reg4.test('bc') ); //false
console.log( reg4.test('bcd') ); //false
console.log( reg4.test('cd') ); //false
console.log( reg4.test('z') ); //true
9.正则表达式之其他配合函数
-
search()
字符串查找函数,在字符串中,查找是否有符合的内容,如果有,返回下标,没有返回-1
返回的是第一个符合内容的索引下标
indexOf() 也是查找,也返回索引下标,但是不支持正则表达式var str1 = 'abcdefgab'; // 默认是区分大小写的 console.log( str1.search('ab') ); //0 console.log( str1.search('B') ); //-1 // 正则表达式,不区分大小写 console.log( str1.search(/B/i) ); //1 console.log( str1.indexOf('b') ); //1 // indexOf() 不支持正则表达式 console.log( str1.indexOf(/B/i) ); //-1
-
match()
找到符合规范的字符串,并且返回内容
默认只会执行一次,并且返回第一次符合规范的内容var str2 = 'abcdefgabcdefg'; var arr1 = str2.match('ab'); // 正则表达式,匹配全局 var arr2 = str2.match(/ab/g); console.log(arr1); // Array [ "ab" ] console.log(arr2); // Array [ "ab", "ab" ]
-
replace()
字符串替换,默认只替换第一个符合的内容var str3 = 'abcd曹abcd曹abcd曹abcd'; // 默认值替换第一个 // str3 = str3.replace('曹' , '*'); // 正则表达式,替换全局 str3 = str3.replace( /曹/g , '*'); console.log(str3); //abcd*abcd*abcd*abcd
10.获取元素的非行间样式
我们在操作 DOM 的时候,很重要的一点就是要操作元素的 css 样式
那么在操作 css 样式的时候,我们避免不了就要获取元素的样式
之前我们说过可以用 元素.style.xxx 来获取
但是这个方法只能获取到元素 行间样式,也就是写在行内的样式 不管是外链式还是内嵌式,我们都获取不到该元素的样式
这里我们就要使用方法来获取了 getComputedStyle 和 currentStyle
这两个方法的作用是一样的,只不过一个在 非 IE 浏览器,一个在 IE 浏览器
11.获取元素的偏移量等属性词
offsetLeft 和 offsetTop
获取的是元左边的偏移量和上边的偏移量
分成两个情况来看
- 没有定位的情况下
获取元素边框外侧到页面内侧的距离 - 有定位的情况下
获取元素边框外侧到定位父级边框内侧的距离(其实就是我们写的 left 和 top 值)
offsetWidth 和 offsetHeight
- 获取元素
内容宽高 + padding宽高 + border宽高
的和
12.认识ECMA6语法
我们所说的 ES5 和 ES6 其实就是在 js 语法的发展过程中的一个版本而已。
比如我们使用的微信
<1>最早的版本是没有支付功能的
<2>随着时间的流逝,后来出现了一个版本,这个版本里面有支付功能了ECMAScript 就是 js 的语法
<1>以前的版本没有某些功能
<2>在 ES5 这个版本的时候增加了一些功能
<3>在 ES6/ECMA2015 这个版本的时候增加了一些功能(ES6是2015年颁布)
因为浏览器是浏览器厂商生产的
<1>ECMAScript 发布了新的功能以后,浏览器厂商需要让自己的浏览器支持这些功能。
<2>这个过程是需要时间的。
<3>所以到现在,基本上大部分浏览器都可以比较完善的支持了。
<4>只不过有些浏览器还是不能全部支持。
<5>这就出现了兼容性问题。
<6>所以我们写代码的时候就要考虑哪些方法是 ES5 或者 ES6 的,看看是不是浏览器都支持。
网址:http://www.ecma-internation
之前声明变量 使用 var 关键字
ECMA6新增关键字 let 声明变量
let和const关键字和var的区别
- let 和 const 不允许重复声明变量
- let 和 const 声明的变量不会在预解析的时候解析,也就是没有声明提升.
- let 和 const 声明的变量会被所有代码块限制作用范围
let和const的区别
- let 声明的变量的值可以改变,const 声明的变量的值不可以改变
- let 声明的时候可以不赋值,const 声明的时候必须赋值
箭头函数
箭头函数是 ES6 里面一个简写函数的语法方式
语法: (函数的行参) => { 函数体内要执行的代码 }
【注】小技巧:适当省略function 和 return关键字。
箭头函数只能简写函数表达式,不能简写声明式函数
语法: (函数的行参) => { 函数体内要执行的代码 }
箭头函数—箭头函数的特殊性
- 箭头函数内部没有 this,箭头函数的 this 是上一层上下文的
- 箭头函数内部没有 arguments 这个参数集合
- 函数的行参只有一个的时候可以不写 () 其余情况必须写
- 函数体只有一行代码的时候,可以不写 {} ,并且会自动 return