js数组.es5与es6总结
数组
数组定义
var arr = []
这是一个空数组,定义带数据的数组:
var arr = ['张三','李四','王五','赵六']
输出结果:
数组中的数据类型没有限制,在实际项目中,数组中通常会存储同一类型的数据。
var arr = ['a',2,false,undefined,{name:"张三"}];
数组这种数据,相当于在一个大空间中,有很多小空间,每个值前面的数字,表示这个小空间的编号,专业术语叫下标。第一个下标永远是0,依次向后递增,最后一个下标是值的个数-1
也就是说,数组这种数据中每个值是有顺序的。
js还提供了一个构造函数,用来创建数组:
var arr = new Array("张三","李四","王五")
这两种方式定义的数据是一样的。
有一种情况,这两种定义方式是不一样的:
var arr = [5]
var brr = new Array(5)
console.log(arr,brr)
[]
形式定义的是一个数组中有一个小空间,其中的值是5;构造函数方式定义的,表示有5个空的小空间。
数组的规律:
第一个值的下标永远是0;
最后一个值的下标永远是值的个数-1。
数组基本操作
数组中值的个数:数组.length
var arr = ['张三',"李四","王五","赵六"];
var arr1 = [1,2,3,4,5,6];
console.log(arr.length); // 4
console.log(arr1.length); // 6
访问数组中的元素:数组[下标]
例:
var arr = ["张三","李四","王五"];
console.log(arr[1]); // 李四
第一个值永远是:数组[0]
;最后一个值永远是:数组[数组.length-1]
添加元素:数组[下标] = 值
例:
var arr = ["张三","李四"];
arr[2] = "王五";
console.log(arr); // (3) ["张三", "李四", "王五"]
arr[10] = "赵六";
console.log(arr); // (11) ["张三", "李四", "王五", empty × 7, "赵六"] 中间还有7个空元素
修改元素:数组[下标] = 值
例:
var arr = ["张三","李四"];
arr[0] = "王五";
console.log(arr); // (2) ["王五", "李四"]
使用说明:如果下标是已经存在的,那赋值操作就是修改数组元素的值,如果下标是不存在,那赋值操作就给数组添加元素。
删除元素:delete 数组[下标]
var arr = [1,2,3];
delete arr[0];
console.log(arr)
这种删除方式,只能删除值,并不能删除小空间。
数组长度的赋值:
var arr = [1,2,3];
arr.length = 0;
console.log(arr) // []
var arr = [1,2,3];
arr.length = 10;
console.log(arr)
var arr = [1,2,3];
arr.length = 1;
console.log(arr) // [1]
遍历数组:
如果要将数组中的所有元素都输出,操作如下:
var arr = ["张三","李四","王五","赵六"];
console.log(arr[0]); // 张三
console.log(arr[1]); // 李四
console.log(arr[2]); // 王五
console.log(arr[3]); // 赵六
从上面输出的代码中可以看出,多次输出是在进行重复动作,并且多次重复之间是有规律可循的,所以可以使用循环进行这个重复动作:
var arr = ["张三","李四","王五","赵六"];
var length = arr.length;
for(var i=0;i<length;i++){
console.log(arr[i]);
}
结果:
这种使用循环将数组中每个元素输出的操作叫做数组的遍历 - 每个元素都经历一次
遍历对象的for in
语法也可以遍历数组:
var arr = ["张三","李四","王五","赵六"];
for(var i in arr){
console.log(arr[i]);
}
两种遍历方式有区别:
var arr = ['a','b','c'];
arr[5] = 'd'
console.log(arr);
for(var i=0;i<arr.length;i++){
console.log(arr[i]);
}
空的空间会遍历出undefined
var arr = ['a','b','c'];
arr[5] = 'd'
console.log(arr);
for(var i in arr){
console.log(arr[i]);
}
空的空间不会被遍历。
var arr = ['a','b','c'];
for(var i=0;i<arr.length;i++){
console.log(i);
}
下标是数字。
var arr = ['a','b','c'];
for(var i in arr){
console.log(i);
}
下标是字符串。所以for in
的语法更适合遍历对象,为了避免不必要的错误,尽量不要用这种语法来遍历数组。
数组练习:
-
利用for循环求数字数组中所有元素的和
var arr = [10,20,30,40,50];
var sum = 0;
for(var i = 0;i < arr.length; i++){
sum += arr[i];
}
console.log(sum); -
有一个数组,具体内容如下:
var arr = [
"越南被曝咖啡造假:咖啡粉里掺加电池芯",
"抗日神剧被当教材:机密文件居然有女优名字",
"王俊凯任联合国大使:系最年轻的联合国大使",
"行人闯红灯遭水喷 目前还在测试阶段",
"68条鱼估价超600万 什么鱼要这么贵?"
]利用循环使用js做出如下图效果:
var arr = [
"越南被曝咖啡造假:咖啡粉里掺加电池芯",
"抗日神剧被当教材:机密文件居然有女优名字",
"王俊凯任联合国大使:系最年轻的联合国大使",
"行人闯红灯遭水喷 目前还在测试阶段",
"68条鱼估价超600万 什么鱼要这么贵?"
];
document.write("<ul>");
for(var i=0;i<arr.length;i++){
document.write("<li>"+arr[i]+"</li>");
}
document.write("</ul>") -
求数组中的最大值
var arr = [1,9,3,6,8,5,4,7,2,12];
// 求出最大值
var length = arr.length;
var max = arr[0];
for(var i=1;i<length;i++){
if(max<arr[i]){
max = arr[i];
}
}
console.log(max); -
把1~100这个100个数字存到数组中
var arr = [];
for(var i=1;i<=100;i++){
arr[arr.length] = i
} -
整理数组数据,模拟京东的商品列表
<script>
var arr = [
{
goodsImg:'https://img30.360buyimg.com/seckillcms/s140x140_jfs/t1/186995/37/12433/183771/60e7ffb3E1b78db87/c5696abfd650ef64.jpg.webp',
goodsname:'荣耀畅玩20 手机 老人机 学生智能机 【咨询加赠华为原装Type-C线】 幻夜黑 全网通(6G+128G)',
goodsoldprice:'1399',
goodsnowproce:'1029'
},
{
goodsImg:'https://img20.360buyimg.com/seckillcms/s140x140_jfs/t1/116335/26/233/214256/5e8998c4E3b5fc871/ec122a9622175d7e.jpg.webp',
goodsname:'【纯银999十二生肖七彩建盏】【配银饰鉴定证+礼盒+礼盒袋+收藏证书】天目釉原矿铁胎茶盏主人杯茶具茶 纯手工七彩盏-莲花纯银999',
goodsoldprice:'659',
goodsnowproce:'199'
},
{
goodsImg:'https://img12.360buyimg.com/seckillcms/s140x140_jfs/t1/182318/5/13135/123400/60e55430E14b60a71/070af11351a8de90.jpg.webp',
goodsname:'风味坐标 手撕牛肉干 400g(经典原味) 内蒙古锡林浩特特产 高蛋白休闲零食',
goodsoldprice:'229',
goodsnowproce:'69'
},
{
goodsImg:'https://img11.360buyimg.com/seckillcms/s140x140_jfs/t1/185818/10/12878/72765/60e41060Ed9ebc1a3/5fa7730180a53328.jpg.webp',
goodsname:'蔬果园蓝风铃香水洗衣液除菌液母婴可用持久留香酵素英式香氛香味洗衣液洁净家庭组合套装 蓝风铃2kg*3+500g*5袋+留香珠18g*2',
goodsoldprice:'159',
goodsnowproce:'119'
},
];
// 遍历数组,输出标签
for(var i=0;i<arr.length;i++){
document.write('<li>');
document.write('<img src="' + arr[i].goodsImg + '">');
document.write('<h4>'+arr[i].goodsname+'</h4>');
document.write('<b>'+arr[i].goodsnowproce+'</b>');
document.write('<span>'+arr[i].goodsoldprice+'</span>');
document.write('</li>');
}
</script>
<style>
li{
list-style-type: none;
padding: 0;
margin: 0;
width: 140px;
height: 190px;
border:1px solid #000;
float:left;
margin:0 10px;
}
li h4{
width: 140px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
padding: 0;
margin: 0;
}
</style>
数组嵌套
数组中的值类型是没有限制的,所以数组中也可以存储数组。
var arr = [
"Jack",
"Rose",
["王宝强","马蓉"],
["贾乃亮","李小璐"]
];
console.log(arr);
console.log(arr[2]);
console.log(arr[2][1]);
效果:
包含数组的数组,叫做多维数组,我们用的最多的就是二维数组。
var arr = [
'王宝强',
'贾乃亮',
[
'岳云鹏',
'陈伟霆',
'刘诗诗',
[
'刘德华',
[
'张艺兴',
'周笔畅'
]
]
]
];
var brr = arr[2]
console.log(brr); // ['岳云鹏', '陈伟霆','刘诗诗',[ '刘德华',[ '张艺兴','周笔畅' ]]]
var crr = brr[3]
console.log(crr); // [ '刘德华',[ '张艺兴','周笔畅' ]]
var drr = crr[1]
console.log(drr); // [ '张艺兴','周笔畅' ]
var z = drr[1]
console.log(z); // 周笔畅
var zz = arr[2][3][1][1]
console.log(zz); // 周笔畅
基础类型和引用类型
js中允许出现的数据:number、string、boolean、null、undefined、{}、[]、function
根据不同类型的数据存储方式以及赋值方式的不同,我们将数据分为两类:基本类型和引用类型。
基础数据类型:number、string、boolean、undefined、null
引用数据类型:[]、function, {}
基础类型和引用类型的区别:
-
存储方式不同
基础类型将值存在栈内存中;引用类型将值存在堆内存中,将堆内存的内存地址存在栈中。
var a = 1;
var obj = {name:"张三",age:12} -
赋值过程不同
基础类型赋值时,将值复制给另一个变量;引用类型赋值时,将栈中的地址复制给别的变量。
var a = 1
var b = a;
a = 2;
console.log(b) // 2复制值以后,修改其中一个,另一个不会受到影响。
var arr = ['a','b','c'];
var brr = arr;
arr[0] = 'd'
console.log(brr) // ['d','b','c'];当改变其中一个变量中的值,另一个变量中的值也会发生改变。
-
全等的比较规则不同
基础类型全等比较的时候,比较类型和值;
var a = 1;
var b = 1;
console.log(a === b)引用类型全等比较的时候比较栈中存的内存地址是否相同。
var arr = [1,2,3];
var brr = [1,2,3]
console.log(arr === brr)
数组方法
如何给数组的开头添加一个元素?
var arr = ['a','b','c']
for(var i=arr.length-1;i>=0;i++){
arr[i+1] = arr[i]
}
arr[0] = 'd'
console.log(arr)
这样操作起来比较复杂。为了方便我们对数组进行操作,js提供了一些方法,可以快速的操作数组:
-
unshift - 给数组开头添加一个或多个元素 - 返回数组新长度
var arr = ['a','b','c'];
var l = arr.unshift('d')
console.log(arr) // ['d','a','b','c']
console.log(l) // 4 -
push - 给数组的末尾添加一个或多个元素 - 返回数组新长度
var arr = ['a','b','c'];
var l = arr.push('d')
console.log(arr) // ['a','b','c','d']
console.log(l) // 4 -
shift - 删除数组的第一个元素 - 返回被删掉的元素
var arr = ['a','b','c'];
var ele = arr.shift()
console.log(arr) // ['b','c']
console.log(ele) // 'a' -
pop - 删除数组最后一个元素 - 返回被删掉的元素
var arr = ['a','b','c'];
var ele = arr.pop()
console.log(arr) // ['a','b']
console.log(ele) // 'c'
-
splice - 对数组做增、删、改的操作
var arr = ['a','b','c']
// 改 - 参数1:开始下标;参数2:删除的个数;参数3:在删除的位置放上的新的元素 - 可以是多个
arr.splice(1,1,'d') // ['a','d','c']
// 增
arr.splice(1,0,'d') // ['a','d','b','c'] - 删除0个,就是不删除,然后放上新元素
// 删 - 第三个参数可以省略
arr.splice(1,0) // ['a','c'] -
concat - 数组的拼接
var arr = ['a','b','c'];
var brr = ['d','e','f'];
// 将arr和brr合成一个更大的数组
var crr = arr.concat(brr) // ['a','b','c','d','e','f']
// 将一个或多个值和数组合并成一个大数组
var crr = arr.concat(1,2,3)// ['a','b','c',1,2,3] -
sort - 数组的排序
var arr = [9,5,3,7,1,6,4,8,2];
arr.sort() // 默认升序
console.log(arr) // [1,2,3,4,5,6,7,8,9]
arr.sort(function(a,b){ // a代表前面的数,b代表后面的数
return a-b; // 升序 - 如果前面的数-后面的数>0,则交换位置
return b-a; // 降序 - 如果后面的数-前面的数>0,则交换位置
}) -
reverse - 数组的反转
var arr = ['a','b','c'];
arr.reverse()
console.log(arr) // ['c','b','a'] -
join - 将数组中的元素使用指定的连接符连接在一起
var arr = ['a','b','c'];
var str = arr.join('_') // 参数是连接符
console.log(str) // a_b_c
var str = arr.join() // 默认使用逗号连接
console.log(str) // a,b,c
var str = arr.join('')
console.log(str) // abc -
slice - 截取数组
var arr = ['a','b','c','d','e','f'];
// 将数组中的 'b','c','d'截取出来,组成新的数组
var brr = arr.slice(1,4) // 参数1是开始截取的下标,参数2是截取的结束下标,结果中不包含结束下标对应的元素
console.log(brr) // ['b','c','d']
// 如果省略第2个参数,默认从开始下标截取到数组末尾
var crr = arr.slice(1)
console.log(crr) // ['b','c','d','e','f']
冒泡排序
相邻两个元素进行比较,将一个数组中的数字使用循环进行升序或降序的排列
var arr = [3,2,1]; // ---> [1,2,3]
// 相邻的元素比较,就是下标i的元素跟下标i+1的元素比较 - 所以循环要比正常的遍历少一次
for(var i=0;i<arr.length-1;i++){
// 如果前面的元素比后面的元素大
if(arr[i]>arr[i+1]){
// 则交换位置
var tmp = arr[i]
arr[i] = arr[i+1]
arr[i+1] = tmp
}
}
// 这个循环结束后,arr变为:[2,1,3]
// 所以需要继续排列
for(var i=0;i<arr.length-1;i++){
// 如果前面的元素比后面的元素大
if(arr[i]>arr[i+1]){
// 则交换位置
var tmp = arr[i]
arr[i] = arr[i+1]
arr[i+1] = tmp
}
}
// 这个循环结束后,arr变为:[1,2,3]
// 两个循环代码是重复的,所以用循环处理。3个元素循环两次,4个元素循环3次,所以循环重复的次数也是数组长度-1
for(var j=0;j<arr.length-1;j++){
for(var i=0;i<arr.length;i++){
if(arr[i]>arr[i+1]){
var tmp = arr[i]
arr[i] = arr[i+1]
arr[i+1] = tmp
}
}
}
// 如果要降序排序,就将判断条件中的>改为<即可
选择排序
降序:先找最大值,排在最左边,再找第二大的值,往左边靠...,已经排好的,不再参与比较
var arr = [3,2,1]; // ---》 [1,2,3]
// arr[0]放最小的值,所以将arr[0]跟后面所有值比较,如果有比arr[0]更小的,就跟arr[0]交换位置
for(var i=1;i<arr.length;i++){
if(arr[0]>arr[i]){
var tmp = arr[0]
arr[0] = arr[i]
arr[i] = tmp
}
}
// 此时的数组:[1,3,2]
// 第1个位置的数字排好了,排第2个位置上的数字
// arr[1]放剩下的数字中最小的,使用arr[1]跟后面的数字比较,如果有比arr[1]更小的,就跟arr[1]交换位置
for(var i=2;i<arr.length;i++){
if(arr[1]>arr[i]){
var tmp = arr[1]
arr[1] = arr[i]
arr[i] = tmp
}
}
// 此时的数组:[1,2,3]
// 重复代码用循环处理,3个数排2次,4个数排3次
for(var j=0;j<arr.length-1;j++){
for(var i=j+1;i<arr.length;i++){
if(arr[j]>arr[i]){
var tmp = arr[j]
arr[j] = arr[i]
arr[i] = tmp
}
}
}
// 如果要进行降序排列,就将判断条件中的>换成<即可
数组概念:
{}与object区别
数组定义
数组array
数组细节
5、当使用【】定义数据时,如果【】中只有一个数据时,此时代表大空间中只有一个数据是这个数字;当使用new array()定义数据是,如果()中只有一个数字,表示大空间的小空间
数组操作
下标=索引
数组的遍历
使用循环处理重复 - 利用循环遍历数组
倒着循环
对象遍历与数组的遍历
区别2
建议大家使用i=0的方式遍历
obj显示的数据是自己定义的键
数组练习
重要
遍历是为了验证假设成立
通过数组渲染京东商品案例
等量代替
数组嵌套
基础类型和引用类型
比较
基础类型会将数据存储在栈中
数组方法
考试错题
只要是具体的值就能是实参
常量和变量
es5
ES5的语法
js在产生的时候,年代比较早,当时的web需求比较少,所以刚开始的js功能比较少,语法没有特别严谨。随着时代的发展和web应用的普及,js需要更多的功能,以及更严谨的语法,所以,js会有版本的升级。第一版的js是ECMA一开始统一了标准以后的版本。我们现在的所使用的语法,大多是ECMAScript版本3的语法,简称es3。到目前为止,已经有了es7,8,9,甚至es10 的版本了。近几年,基本每年都会有新的版本更新。
每个版本的更新,都需要浏览器支持才能运行,但浏览器不会在js更新之后,立马更新。所以有的版本出来之后,需要在很长时间之后,浏览器才会兼容他。到目前为止,我们公认,es5是兼容性最好的版本。
es5比起我们所正在使用的es3,语法没有什么变化,增加了一个严格模式,还有一些数组的方法。
严格模式
由于js的作用域和隐式声明变量等语法会造成很多预想不到的错误,所以ES5中新增了一个严格模式的语法,用于严格规范代码的书写。
使用语法:
"use strict";
使用说明:
-
要放在代码的最前面,也就是在script标签中的第一行或者某个函数中的第一行,否则会失效
-
严格模式可以规范当前script标签或者当前函数中的代码,不能规范别的script标签中的代码和别的函数
规范的语法:
-
不允许隐式声明变量
-
禁止函数中的形参重名
-
禁止函数中的this代表window
为什么要使用严格模式?
-
可以让代码更加规范
-
可以让代码运行起来更快,提高运行效率
新增数组方法
indexOf方法
查找某个元素在数组中第一次出现的位置
语法:
arr.indexOf(元素,[开始查找的起始下标]);
# 参数1:将要查找的元素
# 参数2:可选项。从哪个下标开始往后查找
# 返回值:如果找到了,就返回这个元素在数组中的下标,如果没有找到,就返回-1
例:
var arr = [1,3,5,7,7,5,3,1];
console.log(arr.indexOf(5)); // 2 - 查找数字5在数组中第一次出现的下标
console.log(arr.lastIndexOf(5)); // 5 - 查找数字5在数组中最后一次出现的位置
console.log(arr.indexOf(5,3)); // 5 - 从下标2开始查找数字5在数组中第一次出现的位置
console.log(arr.lastIndexOf(5,4)); // 2 - 从下标4开始查找数字5在数组中最后一次出现的下标
console.log(arr.indexOf("5")); // -1 - 数组中全是数字,找不到字符串5,所以返回-1
forEach方法
用于遍历数组
语法:
arr.forEach(function(值, 下标, 当前数组){
// 代码段
});
# 在这个方法中需要传入一个函数参数,这个函数的参数说明如下:
# 参数1:数组遍历出来的每个值
# 参数2:可选项。数组遍历出来的每个值对应的下标
# 参数3:可选项。被遍历的当前数组
例:
var arr = [1, 2, 3, 4, 5];
arr.forEach(function(x, index, a){
console.log(x + '|' + index + '|' + (a === arr));
});
// 输出为:
// 1|0|true
// 2|1|true
// 3|2|true
// 4|3|true
// 5|4|true
使用说明:
这个方法没有返回值,返回值为undefined,不会改变原来数组的值。
map方法
遍历数组,并将每个元素经过函数处理后,形成新的元素,所有新元素组成新数组返回
语法:
arr.map(function(值,下标,当前数组){
return 新的值 - 通常新的值是由旧的值处理以后得到
});
例:
var arr = [1, 2, 3, 4, 5];
var arr2 = arr.map(function(item){
return item*item;
});
console.log(arr2); //[1, 4, 9, 16, 25]
使用说明:
这个方法主要用于以同样的规则处理数组中的每个值,并组成新的数组返回
filter方法
将数组中满足指定条件的值,组成新的数组返回
语法:
arr.filter(function(值, 下标, 当前数组){
return 筛选条件
});
例:
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var arr2 = arr.filter(function(v, index) {
return v>5
});
console.log(arr2); //[6, 7, 8, 9, 10]
使用说明:
使用方法和功能跟map方法很像,只是运行规则不一样。map方法中的函数,用于返回新的元素,而filter方法中的函数,根据返回true或false来筛选元素
字符串
字符串的重新认识
字符串定义:
var str = '';
var str = "";
var str = new String()
这三种定义方式没有区别。
字符串中字符的个数:字符串.length
字符串中获取某个字符的时候,可以根据下标来获取:
var str = "abcdef";
var s = str[1]
console.log(s) // 'b'
var s1 = str[0]
console.log(s1) // 'a'
所以字符串也是可以进行遍历的:
var str = "abcdef";
for(var i=0;i<str.length;i++){
console.log(str[i],i)
}
那字符串是否也可以像数组一样,通过下标更改其中的某个字符呢?
var str = 'abcdef';
str[str.length] = 'g'
str[0] = 'g'
console.log(str) // abcdef
操作后,字符串并没有新增和更改。
因为字符串是只读数据,只能读,不能增删改。
字符串可以进行比较,我们在前面的时候,有过这样的比较:
console.log('12'>'5') // false
console.log('12'<'5') // true
字符串可以比较,但是规则跟数字比较是不一样的。
字符串比较的规则是逐字符进行比较,大小由阿斯克码来决定。
阿斯克码
计算机内部只能识别2进制数据,不能识别字母等字符。
为了能让计算机识别字符,科学家制定了一个对照表,当输入一段2进制指令的时候,就能显示成某个字符。
这个对照表叫做阿斯克码表,其中包含了128个常用字符跟2进制的对照关系。
通过阿斯克码表,我们可以得出一些字符串比较的规律:
-
字母比数字大
-
小写字母比大写字母大
-
字母越靠后越大
字符串能比较大小,中文汉字也是字符串,中文汉字也能比较大小:
console.log('我'>'你') // true
console.log('你'>'我') // false
中文汉字的大小由unicode来决定。
阿斯克码总共128个,包含符号、大小写英文字母、数字。阿斯克码是由美国人创建的,所以对于英文的支持非常好。后来随着计算机的普及,各个国家在使用计算机的时候,没办法使用本国文字,这样用起来非常困难。所以众多国家的科学家一起制定了一个更大的对照表,包含各个国家的文字符号,所以称之为万国码,也叫作unicode。
其实unicode就是更大的阿斯克码。
字符串方法
-
charCodeAt - 根据指定下标获取对应的字符的阿斯克码
var str = 'abcdef';
// 获取下标为3的字符的阿斯克码
var res = str.charCodeAt(0); // 参数为指定的下标
console.log(res); // 97 -
String.fromCharCode - 根据指定的阿斯克码得到对应的字符
// 获取98对应的字符
var res = String.fromCharCode(98); // 参数为指定的阿斯克码
console.log(res); // b -
indexOf - 查找字符或子字符串在大字符串中第一次出现的位置
var str = 'i love you';
// 找到o字符在str中第一次出现的位置
var s = str.indexOf('o'); // 参数为要查找的字符
console.log(s); // 3
var s = str.indexOf('o',4); // 参数2为开始查找的下标
console.log(s) // 8
var s = str.indexOf('a') // 查找a字符在字符串中第一次出现的下标
console.log(s) // -1 - 找不到就返回-1 -
lastIndexOf - 查找字符在字符串中最后一次出现的下标
var str = 'i love you';
// 找到o字符在str中最后一次出现的位置
var s = str.lastIndexOf('o');
console.log(s); // 8
var s = str.lastIndexOf('o',7) // 将下标7当做字符串末尾,查找字符o在字符串中最后一次出现的下标
console.log(s) // 3
var s = str.lastIndexOf('a')
console.log(s) // -1 - 找不到就返回-1 -
slice - 截取字符串
var str = 'abcdef';
// 从下标1截取到下标4
var s = str.slice(1,4) // 参数1是开始截取的下标,参数2是截取的结束下标
console.log(s) // bcd - 结果中不包含结束下标对应的字符
var s = str.slice(1) // 省略第二个参数,默认能截取到字符串末尾
console.log(s) // bcdef
var s = str.slice(-3,-1) // 下标可以使用负数表示,-3表示倒数第3个字符,-1表示倒数第1个字符
console.log(s) // def
var s = str.slice(-1,-3) // 如果开始下标比结束下标大,会截取到空
console.log(s) // '' -
split - 将字符串使用指定的分隔符分割为数组
var str = 'a-b-c-d';
var arr = str.split('-') // 参数为分隔符,使用-将字符串分割为一个数组
console.log(arr) // ['a','b','c','d']
var arr = str.split('-',3) // 参数2表示数组中要保留前几个元素
console.log(arr) // ['a','b','c']
var str = 'abcd';
var arr = str.split() // 省略了分隔符,默认就不分割,将整个字符串当做一个元素放在数组中
console.log(arr) // ['abcd']
var arr = str.split('')
console.log(arr) // ["a", "b", "c", "d"] -
replace - 使用新字符串将字符串中某一部分替换掉
var str = '你的头发还好吗?';
str = str.replace('头发','眉毛') // 参数1是被替换的字符串中的部分,参数2是新内容
console.log(str) // '你的眉毛还好吗?'
str = str.replace('','哈哈') // 参数1为空,就会将新内容添加到原字符串的最前面
console.log(str) // '哈哈你的眉毛还好吗?' -
trim - 去除字符串两端空白
var str = ' aaa ';
str = str.trim()
console.log(str) // 'aaa' - 左右两端的空白被去掉了
str = str.trimLeft() // 去除左边的空白
console.log(str) // 'aaa '
str = str.trimRight() // 去除右边的空白
console.log(str) // ' aaa' -
toUpperCase - 将字符串中字母转为大写
var str = 'i love you';
str = str.toUpperCase()
console.log(str) // 'I LOVE YOU' -
toLowerCase - 将字符串中字母转为小写
var str = 'I LOVE YOU';
str = str.toLowerCase()
console.log(str) // 'i love you' -
substr - 截取字符串
var str = 'abcdef';
str = str.substr(1,3) // 参数1是开始截取的下标,参数2是截取的字符串长度
console.log(str) // bcd
str = str.substr(1) // 省略参数2默认截取到字符串末尾
console.log(str) // bcdef
str = str.substr(-4,2) // 开始截取的下标可以用负数表示
console.log(str) // 'cd'
str = str.substr(1,20) // 长度超出最大下标,就相当于省略了参数2
console.log(str) // cdef -
substring - 截取字符串
var str = 'abcdef'
str = str.substring(1,4) // 参数1是开始截取的下标,参数2是结束下标
console.log(str) // bcd - 结果不包含结束下标对应的字符
str = str.substring(1) // 省略参数2,默认截取到末尾
console.log(str) // bcdef
str = str.substring(1,1) // 开始下标和结束下标相等就截取到空字符串
console.log(str) // ''
str = str.substring(4,1) // 开始下标大于结束下标,就先交换两个参数位置,然后再截取
console.log(str) // 'bcd'
str = str.substring(-5,4) // 开始下标或结束下标是负数,就先替换为0,然后开始截取
console.log(str) // abcd
-
数学处理
Math常用API
-
圆周率
Math.PI // 3.1415926535
-
生成随机数
Math.random()
生成的是0~1之间的随机小数,通常在实际项目中需要获取到一个范围内的随机整数,利用这个随机小数封装一个获取范围内的随机整数的函数:
function getRandom(a,b){
var max = a;
var min = b;
if(a<b){
max = b;
min = a;
}
return parseInt(Math.random() * (max - min)) + min
} -
向上取整
向上取整的含义是一个数字的小数部分不够1,将他处理成1。例如:10条数据每页展示3条,前3页都能放3条数据,但是第4页只能放1条数据,虽然占不满1页,但也要占1页
Math.ceil(3.3) // 4
-
向下取整
向下取整跟
parseInt()
是一个意思,只要整数部分,舍掉小数部分得到整数Math.floor(3.9) // 3
-
四舍五入
Math.round(3.3) // 3
Math.round(3.9) // 4 -
求次方
Math.pow(2,3) // 2的3次方,参数1是底数,参数2是幂数
-
绝对值
Math.abs(-6) // 6
Math.abs(6) // 6 -
最大值
Math.max(9,5,1,3,4,8,2,6) // 9
-
最小值
Math.max(9,5,1,3,4,8,2,6) // 1
-
正弦
Math.sin(Math.PI*30/180) // 0.5
-
余弦
Math.cos(Math.PI*60/180) // 0.5
进制的转换
10进制转其他进制:
10进制数字.toString(进制数)
var x = 110;
x.toString(2) // 转为2进制
x.toString(8) // 转为8进制
x.toString(16) // 转为16进制其他进制转10进制:
parseInt(数据,进制数)
var x = "110" // 这是一个二进制的字符串表示
parseInt(x, 2) // 把这个字符串当做二进制, 转为十进制
var x = "70" // 这是一个八进制的字符串表示
parseInt(x, 8) // 把这个字符串当做八进制, 转为十进制
var x = "ff" // 这是一个十六进制的字符串表示
parseInt(x, 16) // 把这个字符串当做十六进制, 转为十进制时间日期处理
js提供了一个构造函数
Date
,用来创建时间日期对象。所以跟时间日期有关的操作都是通过时间日期来操作的。时间日期对象创建
var date = new Date()
console.log(date) // Tue Jul 30 2019 21:26:56 GMT+0800 (中国标准时间)创建好的是一个对象,但是当输出的时候被浏览器自动转为字符串输出了。获取到的是当前本地的时间日期对象。如果把本地的时间日期改掉,获取到的时间日期对象会随着本地时间变化。
获取具体的时间日期
通过时间日期对象可以获取到具体的年月日时分秒,甚至毫秒和时间戳。
date.getFullYear(); // 获取到完整的时间日期对象中的年份
date.getMonth(); // 获取到时间日期对象中的月份 - 这里的月份是通过0~11来描述1~12月的
date.getDate(); // 获取到时间日期对象中的日
date.getDay(); // 获取时间日期对象中的星期几
date.getHours(); // 获取到时间日期对象中的时
date.getMinutes(); // 获取到时间日期对象中分
date.getSeconds(); // 获取到时间日期对象中的秒
date.getMilliseconds(); // 获取到时间日期对象中的毫秒 - 1秒=1000毫秒
date.getTime(); // 获取到时间日期对象对应的时间戳时间戳,指的是,格林尼治时间1970年1月1日0点0分0秒到现在走过的毫秒数。利用时间戳可以方便计算时间,例如:计算100天以前是几月几号。
将年月日时分秒放在页面中显示:
var date = new Date();
var year = date.getFullYear();
var month = date.getMonth()+1;
var d = date.getDate();
var day = date.getDay();
var hour = date.getHours();
var minute = date.getMinutes();
var second = date.getSeconds();
document.write("现在是北京时间:"+year+"年"+month+"月"+d+"日。星期"+day+"。"+hour+"时"+minute+"分"+second+"秒");设置时间日期
通过时间日期对象,可以将其中的年月日时分秒进行设置,改变时间日期对象的时间。
date.setFullYear(年份); // 设置时间日期对象中的年份
date.setMonth(当前月份-1); // 设置时间日期对象中的月份 - 这里的月份是通过0~11来描述1~12月的
date.setDate(日); // 设置时间日期对象中的日
date.setHours(时); // 设置时间日期对象中的时
date.setMinutes(分); // 设置时间日期对象中分
date.setSeconds(秒); // 设置时间日期对象中的秒
date.setMilliseconds(毫秒); // 设置时间日期对象中的毫秒
date.setTime(时间戳); // 设置时间日期对象对应的时间戳 - 直接用时间戳就能将时间日期对象中的年月日时分秒全部改变星期几是不能设置的,是根据年月日生成的。
创建指定的时间日期对象
我们可以在创建时间日期对象的时候就指定时间:
var date = new Date("年-月-日 时:分:秒") // 也可以是英文版的时间字符串 - Sun May 13,2016
var date = new Date(年,月-1,日,时,分,秒)
var date = new Date(时间戳)日期格式化
date.toLocalString();//本地风格的日期格式
date.toLocaleDateString(); // 获取日期
date.toLocaleTimeString(); // 获取时间时间戳的获取
格林威治时间/格林尼治时间
Date.parse("2015-08-24") // 获取1970年到设定时间的毫秒数
new Date().getTime()
+new Date();案例:
两个指定的日期相差多少天
var date1=new Date(2010,10,3);
var date2=new Date(2017,9,24);
var day=(date2.getTime()-date1.getTime())/(1000*60*60*24);/*不用考虑闰年否*/
console.log("相差"+day+"天");100天以后是哪年哪月哪日
var date = +new Date()
date += 100 * 24 * 3600 * 1000
var newDate = new Date(date)
var year = newDate.getFullYear()
var month = newDate.getMonth() + 1;
var d = newDate.getDate()
console.log('100天以后是'+year+'年'+month+'月'+d+'日') -
-
-
前面学习的部分是ECMAScript部分,都是基础语法部分。基础语法只是规定的代码如何写,并不能实现很多主流的操作,比如跳转页面,获取浏览器的尺寸等操作。再比如让HTML中的元素动起来。
所以需要学习BOM来操作浏览器。学习DOM来操作HTML标签。
BOM
BOM是三个单词的首拼--Browser Object Model,即浏览器对象模型。
既然是对象模型,那么所有内容,都是用对象来描述的。
BOM中最大的对象叫window,是浏览器窗口对象。他包含了很多浏览器的操作。
window对象中包含的对象 浏览器的信息
浏览器的名称、版本等信息。关于浏览器的信息,window交给了他的子对象navigator去记录。
console.log(window.navigator.appCodeName); // 返回浏览器的代码名
console.log(window.navigator.appName); // 返回浏览器的名称
console.log(window.navigator.appVersion); // 返回浏览器的平台和版本信息
console.log(window.navigator.cookieEnabled); // 返回指明浏览器是否启用cookie的布尔值
console.log(window.navigator.platform); // 返回运行浏览器的操作系统平台
console.log(window.navigator.userAgent); // 返回由客户机发送服务器的user-agent头部的值结果:
浏览器信息 使用说明:其实navigator对象是属于window对象的,但是window是所有对象的顶级对象,所以通常在写的时候,可以省略掉window。
浏览器的历史记录
历史记录的操作是window的子对象history。可以操作网页的前进和后退。
history.back(); # 返回到上一个页面,相当于浏览器的后退按钮
history.forward(); # 前进到下一个页面(下一个页面必须是点击以后的页面),相当于浏览器的前进按钮
history.go()浏览器的地址栏信息
浏览器的地址栏操作,window对象交给了自己的子对象location对象去处理。
console.log(location.hash); // 设置或返回从#开始的url --- 锚点
console.log(location.href); // 设置或返回完整的的url
console.log(location.search); // 设置或返回url中的参数部分方法:
语法:
location.assign("要跳转的地址"); # 这个方法是设置要跳转的地址
location.reload(); # 重新加载本页面
location.replace() # 使用新地址替换掉旧地址(跳转)window.alert("恭喜你!");
window.prompt("请输入数字:",1);
window.confirm("你确定要删除吗?")浏览器窗口尺寸
-
window.innerHeight - 浏览器窗口的高度
-
window.innerWidth - 浏览器窗口的宽度
var w = window.innerWidth;
console.log(w);
var h = window.innerHeight;
console.log(h);说明:
-
这两个属性返回的单位是像素
-
这两个属性计算的范围包含滚动条的区域
浏览器的事件
onload事件:当网页中的所有资源都加在完成之后执行这个事件
window.onload = function(){
console.log("当网页中所有资源加载完成才打印");
}使用说明:通常是将script标签放到head标签中的时候使用。因为放在head中默认是获取不到body中的内容的,但是有了这个事件后,就可以了。
onscroll 滚动事件:当网页滚动条的位置发生改变的时候触发这个事件
window.onscroll = function () {
console.log('浏览器滚动了')
}使用说明:浏览器要有滚动条才行。
浏览器窗口改变事件:resize
window.onresize = function(){
// 当浏览器的窗口大小发生改变的时候触发这个事件
}浏览器滚动的距离
获取文档向下滚动的距离,以下两个都可以:
-
document.documentElement.scrollTop
-
document.body.scrollTop
window.onscroll = function () {
var t = document.documentElement.scrollTop;
console.log(t);
var t1 = document.body.scrollTop;
console.log(t1);
}使用说明:这两个的区别在于当前文档有没有
doctype
,有就用document.documentElement.scrollTop
,没有就用document.body.scrollTop
获取页面向右滚动的距离:
-
document.body.scrollLeft
-
document.documentElement.scrollLeft
使用方式同上。
使用兼容写法:
var t = document.documentElement.scrollTop || document.body.scrollTop;
var l = document.documentElement.scrollLeft || document.body.scrollLeft;短路运算
当我们将一个变量赋值给另一个变量的时候,通常需要做判断:如果这个变量有值就赋值,如果变量没有值或是undefined或null的时候,就赋一个默认的值。这个判断可以省略分支结构使用一个简短的语法来表示 - 短路运算。
短路运算的符号有两个:
||
和&&
var a;
var b = a || 2; // 如果a有值,就将值赋给b,如果a没有值,就给b赋2 - 此时是将2赋给b
var a = 3;
var b = a || 2; // 如果a有值,就将值赋给b,如果a没有值,就给b赋2 - 此时是将a的值赋给b其中的原理:赋值时,先将运算符左右两边的值转为布尔值来进行判断,因为是使用
或者
符号来连接的,所以如果左边为true
,那已经能确定整体的结果是true
,此时就不会执行后面的值,就将这个值赋给变量了;如果左边为false
,并不能确定整体的结果,所以需要执行到后面,就会将后面的值赋给变量。var a;
var b = a && 2; // 如果a有值,就将2赋值给b,如果a没有值,就将a赋给变量 - 此时是将a赋给b
var a = 3;
var b = a && 2; // 如果a有值,就将2赋值给b,如果a没有值,就将a赋给变量 - 此时是将2赋给b其中的原理:赋值赋值时,先将运算符左右两边的值转为布尔值来进行判断,因为是使用
并且
符号来连接的,所以如果左边为true
,那还不能确定整体的结果是,此时就会执行后面的值,就将这个值赋给变量了;如果左边为false
,已经能确定整体的结果,所以不需要执行到后面,就会将前面的值赋给变量。因为在赋值前的判断,是将左右两边的值转为布尔值来判断的,所以只要能转为布尔值的数据都可以进行,包含:
0
null
undefined
false
''定时器
延迟执行:
var timerId = setTimeout(function () {
console.log('我执行了')
}, 1000)
console.log(timerId) // 1使用说明:第一个参数是要执行的函数,第二个参数延迟的时间(单位毫秒)。返回一个数字,表示当前页面中第几个定时器。
每间隔一段时间执行:
var timerId = setInterval(function () {
console.log('我执行了')
}, 1000)使用说明:第一个参数是要执行的函数,第二个参数是间隔的时间(单位毫秒)。返回一个数字,表示当前页面中第几个定时器。
关闭定时器:
定时器返回的数字,就是用来关闭定时器的
clearTimeout(timerId); // 关闭延迟执行的定时器
clearInterval(timerId); // 关闭间隔执行的定时器使用说明:其实这两个方法可以混用。
var timerId = setTimeout(function () {
console.log('倒计时定时器')
}, 1000)
// 关闭延迟执行定时器
clearInterval(timerId)
var timerId2 = setInterval(function () {
console.log('间隔定时器')
}, 1000)
// 关闭间隔定时器
clearTimeout(timerId2)异步操作
异步和同步的概念
张三叫李四一起去吃饭,张三说他还有作业没做完,让李四先去,李四去吃饭,张三在写作业,这两个人做的事情不一样,但是在同一时间段内,两个人的事情在同时做,这就是异步。
张三叫李四一起去吃饭,张三说他还有作业没做完,让李四等一下,李四就等张三做完作业后两个人才一起去吃饭。这就是同步。
同步的操作需要等待,执行起来是有顺序可循的;异步的操作不需要等待,两件事情是同行进行的。
我们平常写的代码都是同步代码,定时器我们接触到的第一个异步代码。
js的特点是单线程的,也就是同一时间只能做一件事情,所以js会将异步代码交给浏览器去处理,因为浏览器是多线程的。
js的线程,会先将所有同步代码执行完,与此同时,浏览器也在处理异步代码(例如正在等待时间),当浏览器中的异步代码到了应该执行的时候了,会将需要执行的异步代码放在一个队列中,进行排队等候;当js线程将所有同步代码执行结束后,会从队列中拿出第一个需要执行的代码去执行,执行过一个以后,再次到队列中拿出第二个需要执行的代码去执行。。。。
js的异步操作,是在所有同步代码执行完成以后才执行异步代码
一般情况代码是按顺序执行的,上一行代码执行结束之前,下一行代码一直在等待,这是同步机制
同步执行示意图 异步代码是等待同步代码都执行完成以后,才运行异步代码,如下图:
异步执行示意图 DOM
DOM的全拼是:Document Object Model,叫做文档对象模型,主要用于操作html文档。例如,改变标签的北京颜色,让标签移动产生动画。。。。
DOM中的顶级对象是document,言外之意,DOM其实是属于BOM的。
例如:
window.document.write();
window.document.bgColor="red";html基本结构的操作:
-
document.body :body比较常用, 并且在页面中是唯一的, 因此可以使用document.body直接获取
-
document.documentElement : 可以获取html元素及其所有内容
-
document.head : 可以直接获取head元素
-
document.title : 可以直接获取title的文本
获取元素
在js中,标签的id名,可以当做是变量,直接就能代表这个标签元素,但是,id名可以随便定义,但是变量名不能随便定义,所以使用id名代表标签是有风险的。所以需要通过方法来获取到标签元素,自己定义给变量,可以避免这种风险。
通过document获取节点
document.getElementById("标签id名"); // 通过标签的id名获取标签
document.getElementsByTagName("标签名"); // 通过标签名获取标签
document.getElementsByClassName("标签类名"); // 通类名获取标签
document.getElementsByName("标签的name属性的值"); // 通过标签的name属性获取标签
// 上述4种获取标签的方法,除了通过id可以准确获取到元素,别的方法都是只能获取到元素的集合(类数组)使用css选择器获取元素:
documen.querySelector(css选择器); // 获取到匹配css的第一个元素
documen.querySelectorAll(css选择器); // 获取到匹配css的所有元素属性操作
自定义属性
元素.setAttribute(属性名,属性值) # 设置元素的属性
元素.getAttribute(属性名); # 获取元素属性
元素.removeAttribute(属性名); # 删除元素属性元素自带属性
元素.属性名 = 值;
console.log(元素.属性名);例:
btn.onclick=function(){
img.src = '2.jpg';
}内容操作
语法:
元素.innerHTML # 代表元素中的所有内容(包含标签)
元素.innerText # 代表元素中的文本内容
表单元素.value
# 单标签操作内容其实就是在操作元素的属性例:
<body>
<div id="box" introduce="区域"><p>我是盒子</p></div>
</body>
<script type="text/javascript">
document.getElementById("box").innerText = "今天你要嫁给我";
var text = document.getElementById("box").innerText;
document.write(text);
document.getElementById("box").innerHTML = "<a href='http://www.baidu.com'>百度</a>";
var content = document.getElementById("box").innerHTML;
console.log(content);样式设置
元素.style.css属性名 = css属性值; # 给标签设置样式
例:
<body>
<style type="text/css">
#box{
width:100px;
height:100px;
background:#f00;
}
</style>
<input type="button" id="btn" value="走你">
<div id="box"></div>
</body>
<script type="text/javascript">
var n = 0;
document.getElementById("btn").onclick=function(){
n += 100;
document.getElementById("box").style.marginLeft = n + "px";
}
</script>这样设置的样式都是行内样式。
元素类名
使用元素的className属性可以设置元素的类名,也可以获取类名
<body>
<div class="box"></div>
<script>
var div = document.querySelector('div')
div.className = 'test'
console.log(div) // <div class="test"></div>
console.log(div.className) // test
</script>
</body> -
兼容性最好
错误
总结
本次小结:
重点es5新增的数组方法:
'indexOf方法'
var a = arr.indexOf(60)查找元素是否存在在数组中,如果存在,返回该元素在数组中的下标,如果不存在,返回-1
'forEach方法'
var a = arr.forEach(function(v,i,a){
v,i,a都是可选项
v代表每个遍历出来的值
i代表每个遍历出来的值的下标
a代表正在遍历的数组
}
'map方法'
var a = Int8Array.map(function(v){将每个元素都经过函数处理,处理成新的元素,将新的元素组成数组返回
一样也有v,i,a都是可选项
var s = v*1.3
return s
})
'filter方法'
var a = arr.filter(function(v){它会自动遍历数组,把每一位值跟条件比较,不成立的就过滤,成立的就组成新的数组并返回
return v<60
})
DOM
DOM 就是我们 html 结构中一个一个的节点构成的。不光我们的标签是一个节点,我们写的文本内容也是一个节点,注释,包括空格都是节点。
DOM节点分三种:元素节点、文本节点、属性节点。元素节点就是我们获取到的标签元素;标签里面的文本就是文本节点、标签上的属性就是属性节点。
元素节点
就是我们各种获取方法获取到的标签元素
document.getElementById();
document.querySeletor();
document.querySeletorAll();
属性节点
我们通过获取属性的方法获取到的标签属性
标签元素.getAttribute();
文本节点
我们通过innerText
获取到的文本内容就是文本节点
获取节点
-
获取所有子节点childNodes
<body>
<div id="box">
<p>
<span>span标签</span>
</p>
</div>
</body>
<script type="text/javascript">
var Odiv = document.getElementById("box");
console.log(Odiv.childNodes);
</script>说明:获取到的时所有节点,包含文本节点、元素节点。元素节点只有子元素,不包括子元素里面的内容
获取元素所有子节点 看图得知:第一个节点时文本节点,代表标签中间的换行和空格,第二个节点是元素节点,第三个节点是文本节点,又是标签中间的换行和空格
-
获取所有子元素节点children
<body>
<div id="box">
<p class="part">
<span>span标签</span>
</p>
</div>
</body>
<script type="text/javascript">
var Odiv = document.getElementById("box");
</script>说明:只获取元素节点,不包含文本节点
获取所有子元素节点 看图得知:获取到的是一个伪数组,是一个集合。
-
获取第一个子节点firstChild
<body>
<div id="box">
<p class="part">
<span>span标签</span>
</p>
<a href="#">链接</a>
</div>
</body>
<script type="text/javascript">
var Odiv = document.getElementById("box");
console.log(Odiv.firstChild);
</script>说明:只获取第一个节点,其实就相当于childNodes中的第一个。
获取第一个子节点 看图得知:第一个节点是文本节点,相当于
Odiv.childNodes[0]
。因为div和p标签中间有换行和空格 -
获取最后一个子节点
<body>
<div id="box">
<p class="part">
<span>span标签</span>
</p>
<a href="#">链接</a>
</div>
</body>
<script type="text/javascript">
var Odiv = document.getElementById("box");
console.log(Odiv.lastChild);
</script>说明:只获取最后个节点,其实就相当于childNodes中的最后一个。
获取最后一个子节点 看图得知:第一个节点是文本节点,相当于
Odiv.childNodes[childNodes.length-1]
。 -
获取第一个子元素节点firstElementChild
<body>
<div id="box">
<p class="part">
<span>span标签</span>
</p>
<a href="#">链接</a>
</div>
</body>
<script type="text/javascript">
var Odiv = document.getElementById("box");
console.log(Odiv.firstElementChild);说明:只获取元素节点,不会是文本节点。
获取第一个元素节点 看图得知:获取到的时第一个子元素节点。
-
获取最后一个子元素节点lastElementChild
<body>
<div id="box">
<p class="part">
<span>span标签</span>
</p>
<a href="#">链接</a>
</div>
</body>
<script type="text/javascript">
var Odiv = document.getElementById("box");
console.log(Odiv.lastElementChild);说明:只获取元素节点,不会是文本节点。
获取第一个元素节点 看图得知:获取到的时最后一个子元素节点。
-
获取下一个兄弟节点nextSibling
<body>
<div id="box">
<p class="part">段落标签</p>
<a href="#">链接</a>
<span>span标签</span>
</div>
</body>
<script type="text/javascript">
var oA = document.querySelector("a");
console.log(oA.nextSibling);
</script>说明:获取的是节点,有可能时文本节点。
获取下一个兄弟节点 看图得知:获取的是当前节点的下一个节点,不是元素。
-
获取上一个兄弟节点previousSibling,同上。
-
获取当前节点的下一个兄弟元素节点nextElementSibling
<body>
<div id="box">
<p class="part">段落标签</p>
<a href="#">链接</a>
<span>span标签</span>
</div>
</body>
<script type="text/javascript">
var oA = document.querySelector("a");
console.log(oA.nextElementSibling);
</script>说明:获取是元素节点。
获取下一个兄弟元素节点 看图得知:获取到的是下一个兄弟,是元素节点
-
获取当前节点的下一个兄弟元素节点previousElementSibling,同上。
-
获取父节点parentNode,和parentElement一样
<body>
<div id="box">
<p class="part">段落标签</p>
<a href="#">链接</a>
<span>span标签</span>
</div>
</body>
<script type="text/javascript">
var oA = document.querySelector("a");
console.log(oA.parentNode);
</script>说明:获取到的是元素节点。
获取父节点 父节点是元素节点。
-
获取元素的属性节点attributes
<body>
<a href="#" title="跳转百度">链接</a>
</body>
<script type="text/javascript">
var oA = document.querySelector("a");
console.log(oA.attributes);
</script>说明:获取到是所有属性的集合。
获取属性节点 结果是所有属性组成的伪数组。
节点是有不同分类的。获取到节点后,可以通过节点的属性来判断节点的类型。
常用的操作:
获取所有子元素
获取上一个兄弟元素
获取下一个兄弟元素
获取父元素
节点属性
-
nodeType: 节点类型:元素节点 = 1 属性-2(过时) 注释-8 文本-3 参考链接
<body>
<div id="box" name="hezi">
<p class="part" >段落标签</p>
<a href="#" title="跳转百度">链接</a>
<span>span标签</span>
<!-- div结束 -->
</div>
</body>
<script type="text/javascript">
var Odiv = document.getElementById("box"); // div元素节点
var text = Odiv.firstChild; // 文本节点(中间的换行和空格)
var note = Odiv.lastChild.previousSibling; // 换行和空格前面是注释
var attr = Odiv.attributes[0]; // div的第一个属性,是属性节点
console.log(Odiv.nodeType); // 1
console.log(text.nodeType); // 3
console.log(note.nodeType); // 8
console.log(attr.nodeType); // 2
</script>说明:nodeType属性的值不一样,代表节点的类型不同。
-
nodeName: 节点名称
<body>
<div id="box" name="hezi">
<p class="part" >段落标签</p>
<a href="#" title="跳转百度">链接</a>
<span>span标签</span>
<!-- div结束 -->
</div>
</body>
<script type="text/javascript">
var Odiv = document.getElementById("box"); // div元素节点
var text = Odiv.firstChild; // 文本节点(中间的换行和空格)
var note = Odiv.lastChild.previousSibling; // 换行和空格前面是注释
var attr = Odiv.attributes[0]; // div的第一个属性,是属性节点
console.log(Odiv.nodeName); // DIV
console.log(text.nodeName); // #text
console.log(note.nodeName); // #comment
console.log(attr.nodeName); // id
</script>说明:元素节点的节点名称是大写的标签名;文本节点的节点名称是
#text
;注释节点的节点名称是#comment
;属性节点的节点名称是属性名。 -
nodeValue: 节点值
<body>
<div id="box" name="hezi">
<p class="part" >段落标签</p>
<a href="#" title="跳转百度">链接</a>
<span>span标签</span>
<!-- div结束 -->
</div>
</body>
<script type="text/javascript">
var Odiv = document.getElementById("box"); // div元素节点
var text = Odiv.firstChild; // 文本节点(中间的换行和空格)
var note = Odiv.lastChild.previousSibling; // 换行和空格前面是注释
var attr = Odiv.attributes[0]; // div的第一个属性,是属性节点
console.log(Odiv.nodeValue); // null
console.log(text.nodeValue); // "换行和空格"
console.log(note.nodeValue); // "div结束" -- 注释内容
console.log(attr.nodeValue); // "box" -- 属性值
</script>说明:元素节点没有节点值;文本节点的值就是文本内容;注释节点的内容就是注释的内容;属性节点的内容就是属性的值。
案例:childNodes/过滤空白节点
function delSpaceDom(parentNode) {
var sub_child = parentNode.childNodes;
for (var i = 0; i < sub_child.length; i++) {
if(sub_child[i].nodeType == '3' && sub_child[i].nodeName == '#text' && !/\S/.test(sub_child[i].nodeValue)){//文本节点并且是空的文本节点时,将空文本节点删除
parentNode.removeChild(sub_child[i]);
}
}
return parentNode.childNodes;
}
节点操作
创建节点
属性名 | 语法 | 功能 |
---|---|---|
createElement | document.createElement(元素标签) | 创建元素节点(创建标签) |
createAttribute | document.createAttribute(元素属性) | 创建属性节点(创建属性,只有属性名,没有属性值) |
createTextNode | document.createTextNode(文本内容) | 创建文本节点(创建了一个内容) |
例:
var div = document.createElement("div"); // 创建元素节点
var attr = document.createAttribute("name"); // 创建属性节点
attr.value = 'mybox'; // 给属性节点赋值
div.setAttributeNode(attr); // 将属性节点放入元素节点中
var text = document.createTextNode("内容"); // 创建文本节点
div.appendChild(text); // 将文本节点放入元素中
console.log(div); // 输出元素节点
访问效果:
创建节点及使用 |
---|
插入节点
属性名 | 语法 | 功能 |
---|---|---|
appendChild | 父节点.appendChild(所添加的新节点) | 向节点的子节点列表末尾添加新的子节点 |
insertBefore | 父节点.insertBefore(所要添加的新节点,已知子节点) | 在已知的子节点前插入一个新的子节点 |
例:
<body>
<div id="myid">
大盒子
<div>小何字</div>
</div>
<script type="text/javascript">
var p = document.createElement("p");
var a = document.getElementsByTagName("div")[1];
myid.insertBefore(p,a);
// document.getElementById("myid").appendChild(p);
</script>
</body>
替换节点
将某个子节点替换为另一个
语法:
父节点.replaceChild(要插入的新节点,将被替换的老元素);
例:
<body>
<div id="myid">
大盒子
<div>小何字</div>
</div>
<script type="text/javascript">
var p = document.createElement("p");
var a = document.getElementsByTagName("div")[1];
myid.replaceChild(p,a);
</script>
</body>
复制节点
根据原来的节点复制一个节点出来
语法:
需要被复制的节点.cloneNode(param);
使用说明:param的值是布尔值,为true时表示复制当前节点及其所有子节点(深复制),为false时,表示仅复制当前节点,缺省值为false(浅复制)
<body>
<div id="myid">
大盒子
</div>
<script type="text/javascript">
var n = myid.cloneNode(true);
console.log(n);
</script>
</body>
删除节点
删除指定元素的某个子节点
语法:
父元素.removeChild(要删除的节点);
例:
<body>
<div id="myid">
大盒子
<p id="part">段落</p>
</div>
<script type="text/javascript">
myid.removeChild(part);
</script>
</body>
节点操作总结
创建元素节点
追加子节点
添加到指定子节点前面
复制节点 -- 浅复制和深复制
删除节点
获取元素样式
我们通过元素节点的style属性赋值,就可以给元素添加样式,那能不能通过stlye属性获取元素样式呢?
<body>
<style>
div{background: #0f0;}
</style>
<div style="width:100px;height:100px;border:1px solid #000;"></div>
</body>
<script type="text/javascript">
var ODiv = document.getElementsByTagName("div")[0]; // 获取到div元素
console.log(ODiv.style.width);
console.log(ODiv.style.background);
</script>
访问结果:
使用style属性获取元素样式 |
---|
看图得知:给元素设置的行内样式获取到了,但是获取不到内联样式。
也就是说,style属性只能获取到元素的行内样式。
那么如何获取元素的内联样式以及外联样式呢?
通过window对象的getComputedStyle方法:
语法:
window.getConputedStyle(元素).css属性;
返回一个对象,这个对象中包含了元素所有的样式。
例:
<body>
<style>
div{background: #0f0;}
</style>
<div style="width:100px;height:100px;border:1px solid #000;"></div>
</body>
<script type="text/javascript">
var ODiv = document.getElementsByTagName("div")[0]; // 获取到div元素
var bg = window.getcomputedStyle(ODiv).background;
console.log(bg);
</script>
访问结果:
获取元素样式 |
---|
这个方法在IE中不起作用,那在IE中用什么获取样式?
使用元素的currentStyle属性:
语法:
元素.currentStyle;
这个对象返回的也是一个包含元素所有样式的对象
例:
<body>
<style>
div{background: #0f0;}
</style>
<div style="width:100px;height:100px;border:1px solid #000;"></div>
</body>
<script type="text/javascript">
var ODiv = document.getElementsByTagName("div")[0]; // 获取到div元素
var ODivStyles = ODiv.currentStyle;
console.log(ODivStyles);
</script>
访问结果:
IE下获取元素样式 |
---|
节点操作案例:qq菜单案例
<link rel="stylesheet" href="./font/iconfont.css">
<style>
*{
padding: 0;
margin: 0;
list-style:none;
}
ol{
width:300px;
background-color: pink;
padding-left:10px;
margin:50px auto;
}
h2{
font-size:20px;
height:30px;
line-height:30px;
}
ol ul{
display:none;
}
ol ul li{
font-size:18px;
height:24px;
line-height:24px;
padding-left:2em;
background-color: #666;
color:#fff;
margin:5px 0;
}
</style>
</head>
<body>
<ol>
<li>
<h2><i class="iconfont icon-arrowRight"></i>我的好友</h2>
<ul>
<li>张三</li>
<li>李四</li>
<li>王五</li>
</ul>
</li>
<li>
<h2><i class="iconfont icon-arrowRight"></i>我的坏友</h2>
<ul>
<li>张小三</li>
<li>李小四</li>
<li>王小五</li>
</ul>
</li>
<li>
<h2><i class="iconfont icon-arrowRight"></i>黑名单</h2>
<ul>
<li>张大三</li>
<li>李大四</li>
<li>王大五</li>
</ul>
</li>
</ol>
</body>
<script src="./js/jquery.js"></script>
<script type="text/javascript">
var h2 = document.querySelectorAll("h2");
var onOff = true;
for(var i=0;i<h2.length;i++){
h2[i].onclick=function(){
var oi = this.querySelector("i");
var ul = this.nextElementSibling;
var