web前端开发JavaScript基础-核心原理-项目实战(day4)math的方法、数组的方法、数组去重、字符串、时间、queryURLParameter、验证码、小时钟、时间格式化、获取元素等

#### 一、math
- 数学函数:不是一个函数,是一个对象,对象中存储了很多操作数
字的函数,因此被称为数学函数。
```
console.log(typeof(Math));//=>"object"
console.dir(Math);
/*
 * Math={
 *   PI:3.141592653589793
 *   abs:function(){[native code]}
 *   ceil:function(){[native code]}
 *   ···
 * }
 * Math.abs();
 * Math.PI; 
 */
```
##### Math中常用的属性和方法
### 1.Math.abs([value])
获取绝对值,绝对值永远非负数
```
console.log(Math.abs(-12.5));//=>12.5
console.log(Math.abs(12));//=>12
console.log(Math.abs(0));//=>0
//不是数字类型的值:先基于Number()转换为数字再处理
console.log(Math.abs('-1'));//=>1
console.log(Math.abs('-1px'));//=>NaN
console.log(Math.abs(true));//=>1
```
### 2.Math.ceil/floor([number value])
把一个数向上取整/向下取整
```
console.log(Math.ceil(12));//=>12
console.log(Math.ceil(12.1));//=>13
console.log(Math.ceil(12.9));//=>13
console.log(Math.ceil(-12.1));//=>-12
console.log(Math.ceil(-12.9));//=>-12

console.log(Math.floor(12));//=>-12
console.log(Math.floor(12.1));//=>12
console.log(Math.floor(12.9));//=>12
console.log(Math.floor(-12.1));//=>-13
console.log(Math.floor(-12.9));//=>-13
```
### 3.Math.round()
四舍五入
```
console.log(Math.round(12));//=>12
console.log(Math.round(12.1));//=>12
console.log(Math.round(12.5));//=>13
console.log(Math.round(12.9));//=>13
console.log(Math.round(-12.1));//=>-12
console.log(Math.round(-12.5));//=>-12(负数中 .5舍)
console.log(Math.round(-12.9));//=>-13
```
### 4.Math.max/min([val1],[val2],...)
获取一堆数中的最大值和最小值
```
console.log(Math.max(12,5,68,23,45,3,28));//=>68
console.log(Math.min(12,5,68,23,45,3,28));//=>3

//思考题:如何基于Math.max/min获取数组中的最大值/最小值?
Math.max([12,5,68,23,45,3,28]);//=>NaN 此处只传递第一个值,
是个数组,和内置的语法要求不符
```
### 5.Math.sqrt/pow()
sqrt:给一个数开平方
pow:计算一个数的
```
console.log(Math.sqrt(9));//=>3 
console.log(Math.sqrt(-9));//=>NaN  
console.log(Math.pow(2,10));//=>1024
```
### 6.Math.random()
获取0-1之间的随机小数
```
for (let i = 0; i <= 10; i++) {
    console.log(Math.random());
}
/*
0.2351119504604302
0.8103880292045642
0.9153034803838505
··· 
 */
```
### 扩展:获取[n-m]之间的随机整数
    包含n、m
    n<m
```
Math.round(Math.random()*(n-m)+n)
```

#### 数组及数组中常用的方法
数组是对象数据类型的,它属于特殊的对象
```
let ary=[12,23,34,45];
console.log(typeof(ary));//=>object
console.dir(ary);
/*
ary{
    0:12,
    1:23,
    2:34,
    3:45,
    length:4
} 
数字作为索引(key属性名)
length代表长度

ary[0]根据索引获取指定项的内容
ary.length 获取数组的长度
ary.length-1最后一项的索引
 */
```
### 数组中常用的方法
+ 方法的作用和和含义
+ 方法的实参(类型和含义)
+ 方法的返回值
+ 原来的数组是否会发生改变

1. 实现数组增删改的方法
    这一部分方法都会修改原有的数组

'push'
```
    push:向数组末尾增加内容
    参数:@params
        多个任意类型
    返回值:@return
        新增后数组的长度
let ary=[10,20];
let res=ary.push(30,'AA');
//基于原生JS操作键值对的方法,也可以向末尾追加一项新的内容
ary[ary.length]=40;
console.log(res,ary);//=>4 [10,20,30,'AA',40]
```
'unshift'
```
    unshift:向数组开始位置增加内容
    参数:@params
        多个任意类型
    返回值:@return
        新增后数组的长度
let ary=[10,20];
let res=ary.unshift(30,'AA');
console.log(res,ary);//=>4 [30,'AA',10,20]
```
'shift'
```
    shift:删除数组中的第一项
    参数:@params
    返回值:@return 
    删除的那一项

let ary=[10,20,30,40];
let res=ary.shift();
console.log(res,ary);//=>10 [20,30,40]
//基于原生JS中的delete,把数组当做普通的对象,确实可以删除
某一项内容,但是不会影响数组本身的结构特点(length长度不会
跟着修改),真实项目中杜绝这样的删除使用
delete ary[0];
console.log(res,ary);//=>{1:30,2:40,length:3}
```
'pop'
```pop:删除数组中的最后一项
    参数:@params
    返回值:@return 
    删除的那一项

let ary=[10,20,30,40];
let res=ary.pop();
console.log(res,ary);//=>40 [10,20,30]
//基于原生JS让数组长度删掉一位,默认删除最后一项
ary.length--;//ary.length = ary.length - 1;
console.log(res,ary);//=>40 [10,20]
```
'splice'

```
    splice:实现数组的增加、修改
    参数:@params
    n,m,x 从索引n开始删除m个元素,用x占用删除的部分
    n,0,x 从索引n开始,一个都不删,把x放到索引n的前面
    返回值:@return 
        把删除的部分用新数组存储起来返回
 let ary = [10, 20, 30, 40, 50];
 let res = ary.splice(1,2,'哈哈哈');
 console.log(res, ary);//=>[20,30] [10,'哈哈哈',40,50]

 //实现增加
 ary.splice(3,0,'嘻嘻')
 console.log(ary);//=>[10, '哈哈哈', 40, '嘻嘻', 50]

 //向数组末尾追加
 ary.splice(ary.length,0,'AAA');
 console.log(ary);//=>[10, '哈哈哈', 40, '嘻嘻', 50, 
'AAA']

 //向数组开端追加
 ary.splice(0,0,'BBB');
 console.log(ary);//=>['BBB', 10, '哈哈哈', 40, '嘻嘻',
 50, 'AAA']
 
```

2.数组的查询和拼接
    此组学习的方法,原来数组不会改变
slice
```
 slice:实现数组的查询
    参数:@params
    n,m  都是数字 从索引n开始,找到索引为m的地方(不包含m
这一项)
    返回值:@return 
        把找到的内容以一个新数组的形式返回

let ary=[10,20,30,40,50];
let res=ary.slice(-1,-3);
console.log(res);//=>[20,30]

//m不写是找到末尾
// res=ary.slice(1);
// console.log(res);//=>[20,30,40,50]

//数组的克隆,参加0不写也可以
// res=ary.slice(0);
// console.log(res);//=>[10,20,30,40,50]

//思考: 
// 1.如果n、m是负数会怎么样?若n>m会怎么样?如果是小数会怎么
样?若是非有效数字会怎么样?若m或n的值比最大索引都大会怎么样?
// 若n为负,则无论m是正或负,均为空字符串
// 若n为正,
// 2.这种克隆方式叫浅克隆,深克隆如何处理?
```
'concat'
```
concat:实现数组拼接
    参数:@params
        多个任意类型值
    返回值:@return 
        拼接后的新数组(原来数组不变)
let ary1=[1,2,3];
let ary2=[4,5,6];
let res=ary1.concat('QQQ',ary2);
console.log(res);//=>[1,2,3,'QQQ',4,5,6]
```

3.把数组转换为字符串
    原有数组不变
tostring
```
tostring:把数组转换为字符串
    参数:@params
    返回值:@return 
        转换后的字符串,每一项用逗号分隔(原来数组不变)
let ary=[1,2,3];
let res=ary.toString();
console.log(res); //=>"1,2,3"
console.log([].toString());//=>""
console.log([12].toString());//=>"12"
```

join
```
join:把数组转换为字符串
    参数:@params
        指定的分隔符(字符串格式)
    返回值:@return 
        转换后的字符串(原来数组不变)
        let ary=[1,2,3];
        // let res=ary.join('');
        // console.log(res); //=>"123"
        // let res=ary.join('|');
        // console.log(res); //=>"1|2|3"
        // let res=ary.join();
        // console.log(res);
        let res=ary.join('+');
        console.log(res);
        console.log(eval(res)); //=>eval把字符串变为JS表
达式执行
```

4.检测数组中是否包含某一项
indexof/lasIndexof
```
indexOf / lastIndexOf:检测当前项在数组中第一次或者最后一
次出现位置的索引值(在IE6-8中不兼容)
    参数:@params
        要检索的这一项内容
    返回值:@return 
        这一项出现的位置索引值(数字),如果数组中没有这一
项,返回的结果是-1
    原来数组不变

let ary = [1, 2, 3, 1, 2, 3];
console.log(ary.indexOf(2));//=>1
console.log(ary.lastIndexOf(2));//=>4

//验证ary中是否包含'哈哈哈'
if (ary.indexOf('哈哈哈') === -1){
    //不包含
}
//也可以直接使用ES6新提供的includes方法判断
if(ary.includes('哈哈哈')){
    //包含:如果存在返回的是true
}
```

5.数组的排序或排列
reverse
```
 reverse:把数组倒过来排列
    参数:@params
    返回值:@return 
        排列后的新数组
    原来数组改变
let ary = [12, 15, 9, 28, 10, 22];
ary.reverse();
console.log(ary);//=>[22, 10, 28, 9, 15, 12]
```

sort
```
sort :实现数组的排序
    参数 :@params
        可以没有,也可以是个函数
    返回值 :@return 
        排列后的新数组
    原来数组改变
// let ary = [4,7,5,8,3,6,1,9,2];
// ary.sort();
// console.log(ary);//=>[1, 2, 3, 4, 5, 6, 7, 8, 9]

//sort 方法中如果不传递参数,是无法处理10以上数字排序的(它
默认按照每一项第一个字符来排序,不是按照数值大小排的)
/* let ary = [12, 15, 9, 28, 10, 22];
ary.sort();
console.log(ary);//=>[10, 12, 15, 22, 28, 9] */

//实现多位数正常排序,需要给sort传递一个函数,函数中返回a-b 
实现升序,返回b-a 实现降序(? 需了解冒泡排序的机制)
let ary = [12, 15, 9, 28, 10, 22];
//ary.sort(function(a,b){return a-b});
//a和b是相邻的两项
ary.sort((a, b) => a - b);
console.log(ary);//=>[9, 10, 12, 15, 22, 28]

```
6.遍历数组中每一项的方法
forEach
```
forEach :遍历数组中的每一项内容
    参数 :@params
        回调函数
    返回值 :@return 

    原来数组改变
*/
let ary = [1, 5, 9, 6, 5, 12, 14];

/* //基于原生JS中的循环可以实现
for (let i = 0; i < ary.length; i++) {
    //i:当前循环这一项的索引
    //ary[i]:根据索引获取循环的这一项
    console.log('索引:' + i + '内容:' + ary[i]);
} */

ary.forEach((item, index) => {
    // 数组中有多少项,函数就会被默认执行多少次
    //每一次执行函数:item是数组中当前要操作的这一项,index
是当前项的索引
    console.log('索引:' + index + '内容:' + item);
});
```
map
filter
find
reduce
some
every
····
Array.prototype在控制台查看数组中所有提供的方法,可以基于
MDN网站去查询方法的用法

#### 数组去重
```
let ary = [1, 2, 3, 1, 2, 1, 2, 3, 2, 1, 2, 3];
//=>[1,2,3]

/* 
方案一:
    循环原有数组中的每一项,每拿到一项都往新数组中添加
    添加之前验证新数组中是否存在这一项,不存在再添加
 */
let newAry = [];
for (let i = 0; i < ary.length; i++) {
    //循环获取原有数组中的每一项
    let item = ary[i];
    //验证新数组中是否存在这一项
    if (newAry.includes(item)) {
        //存在这一项,不再增加到新数组,继续下一轮循环即可
        continue;
    }
    //新数组中不存在这一项,我们加入到新数字即可
    newAry.push(item);
}
console.log(newAry);
```
```
//方案一优化
let newAry = [];
ary.forEach(item => {
    if (newAry.includes(item)) return;
    newAry.push(item);
});
console.log(newAry);
```
方案二:
```    先分别拿出数组中的每一项A
    用这一项A和它后边的每一项依次进行比较,如果遇到和当前
项A相同的,则在原来数组中把这一项移除掉

    不用includes/indexOf,保证兼容性

var ary = [1, 2, 3, 1, 2, 1, 2, 3, 2, 1, 2, 3];
for (var i = 0; i < ary.length; i++) {
    //item:每一次循环拿出来的当前项
    //i:当前项索引
    var item = ary[i];
    /* 
    itemLast:当前项后边所有的内容(新数组)
    var itemLast = ary.slice(i + 1); //创建数组耗性能*/
    //i+1:代表后一项
    //让当前项与后边的每一项进行比较(循环)
    for (var j = i + 1; j < ary.length; j++) {
        //compare:后边需要比较的每一项
        var compare = ary[j];
        //如果compare和item相等,说明这一项是重复的,把他删掉
        if (compare === item) {
            //j索引这一项要从数组中移除
            ary.splice(j, 1);
            //数组塌陷了:j后边的每一项索引都提前了一位,下一
次要比较还是j这个索引的内容
            j--;
        }
    }

}
console.log(ary);
```
方案三:
```
let ary = [1, 2, 3, 1, 2, 1, 2, 3, 2, 1, 2, 3];
//1.创建一个空对象
let obj = {};
//2.循环数组中的每一项,把每一项向对象中进行存储 => item:item
for (let i = 0; i < ary.length; i++) {
    let item = ary[i];
    //3.存储之前进行判断:验证obj中是否存在这一项
    if (obj[item] !== undefined) {
        //已经存在这一项
        ary.splice(i, 1);
        i--;
        continue;
    }
    obj[item] = item;//obj[1]=1;···
}
console.log(ary);

```

```
//基于splice实现删除性能不好:当前项被删后,后面每一项的索引都
要向前提一位,如果后面内容过多,定影响性能
/* 
let ary = [1, 2, 3, 1, 2, 1, 2, 3, 2, 1, 2, 3];
let obj = {};
for (let i = 0; i < ary.length; i++) {
    let item = ary[i];
    if (obj[item] !== undefined) {
        ary[i] = ary[ary.length - 1];
        ary.length--;
        i--;
        continue;

    }
    obj[item] = item;//obj[1]=1;···
}
console.log(ary); 
*/

/*
    unique:实现数组去重的方法
    @params
        ary[Array]要去重的数组
    @return
        [Array]去重后的数组
    by ct on 20230214
 */
function unique(ary) {
    let obj = {};
    for (let i = 0; i < ary.length; i++) {
        let item = ary[i];
        if (obj[item] !== undefined) {
            ary[i] = ary[ary.length - 1];
            ary.length--;
            i--;
            continue;
        }
        obj[item] = item;
    }
    return ary;
}
let aa = [1, 5, 6, 8, 12, 1, 2, 5, 6, 15, 47, 12, 47];
aa = unique(aa);
aa.sort((a, b) => a - b);
console.log(aa);
```
//正则
```
let ary = [1, 5, 6, 8, 12, 1, 2, 5, 6, 15, 47, 12, 47];
ary.sort((a, b) => a - b);
let str = ary.join('@') + '@';
let reg = /(\d+@)\1*/g;
console.log(str.match(reg));
ary = [];
str.replace(reg, (n, m) => {
    m = Number(m.slice(0, m.length - 1));
    ary.push(m);
});
console.log(ary);//=>[1, 2, 5, 6, 8, 12, 15, 47]
```

//基于ES6的set(对应的Map)实现去重
```
let ary = [1, 5, 6, 8, 12, 1, 2, 5, 6, 15, 47, 12, 47];
ary = [...new Set(ary)];
console.log(ary);//=>[1, 5, 6, 8, 12, 2, 15, 47]
```

#### 字符串中常用的方法
> 所有用 单引号、双引号、反引号 包起来的都是字符串
```
let str = 'hahahahahah';
//每一个字符串都是由零到多个字符组成的
str.length //=>字符串长度
str[0] //=>获取索引为零(第一个)字符
str[str.length-1] //=>获取最后一个字符str.length-1最后一线
索引str[10000] //=>undefined 不存在这个索引

//循环输出字符串中的每一个字符
let str = 'hahahahahah';
for(let i=0;i<str.length;i++){
    let char = str[i];
    console.log(char);
}
```

`charAt / charCodeAt`
```
charAt:根据索引获取指定位置的字符
charCodeAt:获取指定字符的ASII码值(Unicode编码值)
@params
    n[number] 获取字符指定的索引
@return
    返回查找到的字符
    找不到返回的是空字符串㐊undefined,或者对应的编码值

let str = 'hahahahahah'; 
console.log(str.charAt(0)); //=>'h'  
console.log(str[0]);   //=>'h'
console.log(str.charAt(100));  //=>''
console.log(str[100]);   //=>undefined

console.log(str.charCodeAt(0)); //=>104
console.log(String.fromCharCode(str.charCodeAt(0)));//=>'h'  
```
`substr / substring / slice`
``` 
都是为了实现字符串截取(在原来字符串查找到自己想要的)
substr(n,m):从索引n开始截取m个字符,m不写截取到末尾(其他的
方法也是)
substring(n,m):从索引n开始找到索引m处(不包含m)
slice(n,m):和substring一样,都是找到索引m处,但slice可以
支持负数作为索引,其余两个方法不可以

let str = 'hahahahahaha'; 
console.log(str.substr(3,7));//=>'ahahaha'
console.log(str.substring(3,7));//=>'ahah'
console.log(str.substr(3));//=>'ahahahaha' 截取到末尾
console.log(str.substring(3,100));//=>'ahahahaha' 截取到末
尾(超过索引的也只截取到末尾)

console.log(str.substring(3,7));//=>'ahah'
console.log(str.slice(3,7));
console.log(str.substring(-7,-3));//=>'' substring不支持负
数索引
console.log(str.slice(-7,-3));//=>'nqit' slice支持负数索引 
 快捷查找:负数索引,按照STR.length+负索引的方式找  
=>slice(12-7,12-3) =>slice(5,9) =>ahah
```
`indexof / lastIndexOf / includes`
```
验证字符是否存在
    indexOf(x,y):获取x第一次出现位置的索引,y是控制查找的起
始位置索引
    lastIndexOf(x):最后一次出现位置的索引
    =>没有这个字符,返回的结果是-1

let str = 'hahahahahaha'; 
console.log(str.indexOf('h'));//=>0
console.log(str.lastIndexOf('h'));//=>10
console.log(str.indexOf('!'));//=>-1  不存在返回-1
if(str.indexOf('!')===-1){
    //字符串中不包含!这个字符
}
console.log(str.indexOf('aha'));//=>1 验证整体第一次出现
的位置,返回的索引是第一个字符所在位置的索引值
console.log(str.indexOf('ahan'));//=>-1
console.log(str.indexOf('ha',5));//=>6 查找索引5及之后的
字符串中,ha第一次出现的位置索引

if(!str.includes('!')){
    console.log('当前字符串不包含!');
}
```

`toUpperCase / toLowerCase`
```
字符串中字母的大小写转换
    toUpperCase():转大写
    toLowerCase():转小写

let str = 'Hahahahahaha'; 
str=str.toUpperCase();
console.log(str);//=>'HAHAHAHAHAHA'
str=str.toLowerCase();
console.log(str);//=>'hahahahahaha'
//实现首字母大写
str = str.substr(0, 1).toUpperCase() + str.substr(1);
console.log(str);//=>Hahahahahaha
```

`split`
 ```
    split([分隔符]):把字符串按照指定的分隔符拆分成数组(和
数组里的join相对应)
    split支持传递正则表达式

//需求:把|分隔符变为,分隔符
let str = 'music|movie|eat|sport';
let ary=str.split('|');//=>['music', 'movie', 'eat', 
'sport']
console.log(ary);
str=ary.toString();
console.log(str);//=>music,movie,eat,sport
str=ary.join(',');
console.log(str);//=>music,movie,eat,sport
```

`replacr`
```
 replace(老字符,新字符):实现字符串的替换(经常伴随着正
则使用)

let str='哈喽!你好!是吧?';
/* str=str.replace('!','+');
console.log(str);//=>哈喽+你好!是吧? 在不使用正则表达式
的情况下,执行一次replace只能替换一次字符 */ 
str=str.replace(/!/g,'-');
console.log(str);//=>哈喽-你好-是吧?
```

`match`
`localCompare`
`trim / trimLeft / trimRight`
···
控制台输出string.prototype查看所有字符串中提供的方法

#### 实现一些常用的需求
> 5.时间字符串的处理
```
    let time = '2023-2-14 19:45:45';
    //=>变为自己需要呈现的格式,例如:
    //"2023年2月14日 19点45分45秒"
    //"2023年2月14日"
    //"2/14 19:45"
    //···
    //方案一:
/*
    let time = '2023-2-14 19:45:45';
    time = time.replace('-', '年').replace('-', '月')
.replace(' ', '日 ').replace(':', '时').replace(':', 
'分') + '秒';
    console.log(time);//=>2023年2月14日 19时45分45秒
 */

//方案二:获取年月日时分秒这几个值,按照所想拼出效果

//不足十位补零
/* 
let addZero = val => {
    if (val.length < 2) {
        val = '0' + val;
    }
    return val;
};
 */
let addZero = val => val.length < 2 ? '0' + val : val;
let time = '2023-2-14 19:45:45';
let ary = time.split(/(?: |-|:)/g);//=>['2023', '2', 
'14', '19', '45', '45']
time = ary[0] + '年' + addZero(ary[1]) + '月' + 
addZero(ary[2]) + '日';
console.log(time);//=>2023年02月14日

//获取值的方法:基于split一项项拆分
/*
let time = '2023-2-14 19:45:45';
let n = time.split(' ');//=>["2023-2-14" ,"19:45:45"]
let m = n[0].split('-')//=>["2023","2","14"]
let x = n[1].split(':');//=>["19","45","45"]
console.log(x);
*/

//获取值的方法:基于indexOf获取指定符号索引,基于substring
一点点截取
/* 
let time = '2023-2-14 19:45:45';
let n = time.indexOf('-');
let m = time.lastIndexOf('-');
let x = time.indexOf(' ');
let y = time.indexOf(':');
let z = time.lastIndexOf(':');
let year = time.substring(0, n);
let month = time.substring(n + 1, m);
let day = time.substring(m + 1, x);
console.log(year, month, day); */
```

> 6.实现一个方法ueryURLPqarameter获取一个URL地址问号后边
传递的参数信息
```
// let url = 'http://www.zhufengpeixun.cn/index.html?lx=1&name=zhufeng&teacher=aaa#box';
/*
    结果:{
        lx:1,
        name:'zhufeng',
        teacher:'aaa',
        HASH:'box'
    }
 */

/* //1.获取问号或者井号后边的值
let askIndex = url.indexOf('?');
let wellIndex = url.indexOf('#');
let askText = url.substring(askIndex + 1, wellIndex);
let wellText = url.substring(wellIndex + 1);
console.log(askText, wellText);
// askText="lx=1&name=zhufeng&teacher=aaa" 
// wellText="box"
//2.问号后边值的详细处理
let result = {};
let askAry = askText.split('&');
console.log(askAry);
//=>['lx=1', 'name=zhufeng', 'teacher=aaa']
askAry.forEach(item => {
    //item:当前从数组中循环的这一项
    let n = item.split('=');
    console.log(n);
    // ['lx', '1']
    // ['name', 'zhufeng']
    // ['teacher', 'aaa']
    let key = n[0];
    let value = n[1];
    result[key] = value;
});
result['HASH'] = wellText;
console.log(result);
//=>{lx: '1', name: 'zhufeng', teacher: 'aaa', HASH:
 'box'} */


/*
    queryURLParams:获取URL地址中间问号传参的信息和哈希值
    @params
        URL[string]要解析的url字符串
    @return
        [object]包含参数和哈希值信息的对象
    by ct on 20230214
 */

/* function queryURLParams(url) {
    //1.获取?和#后边的信息
    let askIn = url.indexOf('?'),
        wellIn = url.indexOf('#'),
        askText = '',
        wellText = '';
    //#不存在
    wellIn === -1 ? wellIn = url.length : null;
    //?存在
    askIn >= 0 ? askText = url.substring(askIn + 1, 
wellIn) : null;
    wellText = url.substring(wellIn + 1);
    //2.获取每部分信息
    let result = {};
    wellText !== '' ? result['HASH'] = wellText : 
null;
    if (askText !== '') {
        let ary = askText.split('&');
        ary.forEach(item => {
            let itemAry = item.split('=');
            result[itemAry[0]] = itemAry[1];
        });
    }
    return result;
} 
*/


//基于正则封装、完美
function queryURLParams(url) {
    let result = {},
        reg1 = /([^?=&#]+)=([^?=&#]+)/g;
        reg2 = /#([^?=&#]+)/;
        url.replace(reg1, (n, x, y) => result[x] = y);
        url.replace(reg2, (n, x) => result['HASH'] = x);
    return result;
}


let url = 'http://www.zhufengpeixun.cn/index.html?lx=1&name=zhufeng&teacher=aaa#box';
let paramsObj = queryURLParams(url);
console.log(paramsObj);
```
> 7.实现一个最low的验证码:数字加字幕共四位
验证码的目的:防止外挂程序恶意批量注入的
```
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>简单的验证码</title>
</head>

<body>
    <input type="text" id="codeInp">
    <br>
    <span id="codeBox">aaaa</span>
    <button id="changeCode">看不清,换一张</button>
    <!-- import Js -->
    <script>
        let codeInp = document.getElementById('codeInp'),
            codeBox = document.getElementById('codeBox'),
            changeCode = document.getElementById(
'changeCode');

        /*
            queryCode:获取到四位随机验证码,然后放到指定的盒子中
                @params
                @return
                by ct on 20230214 
         */
        function queryCode() {
            let area = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
0123456789";
            let result = "";
            for (let i = 0; i < 4; i++) {
                //每一次循环都获取一个随机的数字索引
                let ran = Math.round(Math.random(
) * 61);
                //再根据获取的索引从范围字符串中找到对应
的字符,把
找到的字符拼接到最后的结果中
                result += area.charAt(ran);
            }
            //放到盒子里
            codeBox.innerHTML = result;
        }

        //第一次加载页面需要执行方法,让其显示在页面中
        queryCode();
        //点击看不清按钮,需要重新执行方法生成新的验证码
        changeCode.onclick = queryCode;
        //文本框失去焦点的时候:验证用户输入法人内容和验证码是否
相同,给予相关的提示,如果不一样需要重新生成验证码
        //onblur:文本框失去焦点事件
        codeInp.onblur = function () {
            //获取用户和验证码内容(表单元素.value / 非表单
元素.innerHTML 获取内容)
            let val = codeInp.value,
                code = codeBox.innerHTML;
            //不区分大小写的验证(都转小写)
            if (val.toLowerCase() === code.toLowerCase()) {
                alert('温馨提示:验证码输入成功!');
            } else {
                alert('温馨提示:验证码输入错误,请重新输入!');
                codeInp.value = '';
                //重新生成验证码
                queryCode();
            }
        }
    </script>
</body>

</html>
```

#### 8日期对象的基本操作
```
    let time=new Date();
    <!-- 
        获取当前客户端(本机电脑)本地的时间
            这个时间用户是自己可以修改的,不能作为重要的参
考依据
        
    Wed Feb 15 2023 16:07:27 GMT+0800 (中国标准时间)
        获取的结果不是字符串,是对象数据类型的,属于日期对象
(或者说是Date这个类的实例对象)
     -->
    typeOf time;//=>"object"
```
标砖日期对象中提供了一些属性和方法,供我们操作日期信息
· getFullYear()获取年
· getMonth()获取月 结果是0-11代表第一月到第十二月
· getDate()获取日
· getDay()获取星期 结果是0-6代表周日到周六
· getHours获取时
· getMinutes()获取分
· getSeconds()获取秒
· getMillseconds()获取毫秒
· getTime()获取当前日期距离1970/1/1 00:00:00这个日期之间
的毫秒差
· toLocaleDateString()获取年月日(字符串)
· toLocaleString()获取完整的日期字符串
```
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>小时钟</title>
    <!-- import css -->
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        #clockBox {
            position: absolute;
            right: 0;
            top: 0;
            padding: 0 15px;
            line-height: 50px;
            font-size: 20px;
            color: black;
            /* 设置背景渐变色 */
            /* background:lightblue ; */
            background: -webkit-linear-gradient(top left,
 lightcoral, lightcyan);
        }
    </style>
</head>

<body>
    <div id="clockBox">
        2023年02月15日 星期三 16:24:01
    </div>
    <!-- import JS -->
    <script>
        let clockBox = document.getElementById('clockBox');
        /* 
            addZero:不足十补领
                @params
                    val需要处理的值
                @return
                    处理后的结果
            by ct on 20230215
        */

        function addZero(val) {
            val = Number(val);
            return val < 10 ? '0' + val : val;
        }
        /* 
            queryDate:获取当前日期,把其转换为想要的格式
                @params
                @return
            by ct on 20230215
         */
        function queryDate() {
            //1.获取当前日期及详细信息
            let time = new Date(),
                year = time.getFullYear(),
                month = time.getMonth() + 1,
                day = time.getDate(),
                week = time.getDay(),
                hours = time.getHours(),
                minutes = time.getMinutes(),
                seconds = time.getSeconds();
            //2.拼凑成想要的字符串

            let result = year + "年" + addZero(month) + 
"月" + addZero(day) + "日";
            let weekAry = ['日', '一', '二', '三', '四',
 '五', '六'];
            result += " 星期" + weekAry[week] + " ";
            result += addZero(hours) + ":" + addZero
(minutes) + ":" + addZero(seconds);
            //3.把处理好的结果放盒子里
            clockBox.innerHTML = result;
        }
        //加载页面执行方法
        queryDate();

        //定时器控制运动:设置一个setInterval定时器(到达指定时间
做对应的事的东西就是定时器),每隔1000ms执行queryDate方法
        setInterval(queryDate, 1000);
    </script>
</body>

</html>
```

> new Date()除了获取本机事件,还可以把一个时间格式字符串转换为标准
的时间格式
```
new Date("2023/2/15");
//=>Wed Feb 15 2023 00:00:00 GMT+0800 (中国标准时间) 
<!-- 
    支持的格式
        yyyy/mm/dd
        yyyy/mm/dd hh:mm:ss
        yyyy-mm-dd 这种格式IE不支持
 -->
```
#### 9时间字符串格式化案例
```
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>时间格式化</title>
</head>

<body>
    <script>
        let addZero = val => {
            val = Number(val);
            return val < 10 ? '0' + val : val;
        }
        
        /* 
            字符串处理
        */
        function formatTime(time) {
            //1.获取年月日星期
            // let ary=time.split(/(?: |-|:)/g);
            let ary = time.split(' ');
            let aryLeft = ary[0].split('-'),
                aryRight = ary[1].split(':');
            ary = aryLeft.concat(aryRight);
            //=>['2023', '2', '15', '12', '0', '0']
            //2.拼接为想用的格式
            let result = ary[0] + "年" + addZero(ary[1]) +
 "月" + addZero(ary[2]) + "日";

            result += " " + addZero(ary[3]) + ":" + 
addZero(ary[4]) + ":" + addZero(ary[5]);
            return result;
        }
        let time = '2023-2-15 12:0:0';
        //=>"2023年02月15日 12:00:00"
        time=formatTime(time);
        console.log(time);
        //=>2023年02月15日 12:00:00

    </script>
</body>

</html>
```
```
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>时间格式化</title>
</head>

<body>
    <script>
        let addZero = val => {
            val = Number(val);
            return val < 10 ? '0' + val : val;
        }

        /* 
            基于日期对象处理
        */
        <!-- 
        function formatTime(time) {
            //1.把时间字符串变为标准日起对象

            // time = time.replace(/-/g,'/');
            time = time.replace('-', '/');
            time = time.replace('-', '/');
            time = new Date(time);
            //2.基于方法获取年月日等信息
            let year = time.getFullYear(),
                month = addZero(time.getMonth() + 1),
                day = addZero(time.getDate()),
                hours = addZero(time.getHours()),
                minutes = addZero(time.getMinutes()),
                seconds = addZero(time.getSeconds());
            //3.返回想要的结果
            return year+"年"+month+"月"+day+"日"+hours+"时"
+minutes+"分"+
seconds+"秒";
            
        }

        let time = '2023-2-15 12:0:0';
        //=>"2023年02月15日 12:00:00"
        time = formatTime(time);
        console.log(time);
        //=>2023年02月15日 12:00:00
         -->

          /* 
            封装一套公共的时间字符串格式化处理函数
        */
        String.prototype.formatTime = function 
formatTime(template) {
            typeof templete === 'undefined' ? 
templete = "{0}年{1}月{2}日 {3}:{4}:{5}" : null;
            //this:要处理的字符串
            let matchAry = this.match(/\d+/g);
            //模板和数据的渲染(引擎机制)
            templete = templete.replace(/\{(\d+)\}/g, 
(x, y) => {
                let val = matchAry[y] || '00';
                val.length<2?val='0'+val:null;
                return val;
            });
            return templete;
        };
        let time = '2023-2-15 12:0:0';
        //=>"2023年02月15日 12:00:00"
        console.log(time.formatTime());//传一个模板
        //=>2023年02月15日 12:00:00
    </script>
</body>

</html>
```

#### 10.DOM及其基础操作
> DOM:document object model文档对象模型,提供一些属性和
方法供我们操作页面中的元素

+ 获取DOM元素的方法
    - document.getElementById()指定在文档中,基于元素的
ID或者这个元素对象
    //为什么getElementById的上下文只能是document?

    - [context].getElementByTagName()在指定上下文(容器)
中,通过标签名获取一组元素集合
    - [context].getElementByClassName()在指定上下文中,
通过样式类名获取一组元素集合(不兼容IE6-8)
    - document.getElementByName()在整个文档中,通过标签
的NAME属性值获取一组元素(节点)集合(在IE中只有表单元素的
NAME才能识别,所以我们一般只应用于表单元素的处理)
    - document.head / document.body / 
document.documentElement 获取页面中的head/body/HTML三个元素
    - [context].querySelector([selector])在指定上下文中,
通过选择器获取指定的元素对象
    - [context].querySelectorAll([selector])在指定上下文中,
通过选择器获取指定的元素集合
```
//=>querySelector / queryselectorAll 不兼容IE6-8

let box = document.querySelector('#box');
let links = box.querySelectorAll('a');
//links = document.querySelectorAll('#box a');
let aas = document.querySelectorAll('.aa');
```

### 11.JS中的节点和描述节点之间关系的属性
> 节点:Node(页面中所有的东西都是节点)
> 节点集合:NodeList(getElementsByName / querySelectorAll
获取的都是节点集合)
+ 元素节点(元素标签)
    - nodeType:1
    - nodeName:大写的标签名
    - nodeValue:null
+ 文本节点
    - nodeType:3
    - nodeName:'#text'
    - nodeValue:文本内容
+ 注释节点
    - nodeType:8
    - nodeName:'#commen'
    - nodeValue:注释内容
+ 文档节点(document)
    - nodeType:9
    - nodeName:'#document'
    - nodeValue:null
+ ···
描述这些节点之间关系的属性
+ childNodes:获取所有的子节点
+ children:获取所有的元素子节点(子元素标签集合)
+ parent:获取父亲节点
+ firstChild:获取第一个子节点
+ lastChild:获取最后一个子节点
+ firstElementChild / lastElementChild:获取第一个/
最后一个元素子节点(不兼容IE6-8)
+ previousSibling:获取上一个哥哥节点
+ nextSibling:获取下一个弟弟节点
+ previousElementSibling / nextElementSibling:获取
哥哥和弟弟的元素节点(不兼容IE6-8)
+ ···

```
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>节点操作</title>
</head>
<body>
    <ul id="box">
        <!-- 课程大纲 -->
        <li>GIT和NPM操作</li>
        <li>面向对象好原型:研究插件源码,自己写插件</li>
        <li>闭包作用域:堆栈内存处理</li>
        <li id="fangqi">ES6从入门开始</li>
        <li>同步异步编程及核心:微任务、宏任务、事件循环</li>
        <li>DOM及事件模型</li>
        <li>JQuery及源码分析</li>
        <li>设计模式:发布订阅、单例、Promise、PromiseA+</li>
        若觉得上边难,下边更难
        <li>AJAX及跨域解决方案:封装一款牛*的AJAX库</li>
        <li>一入http深似海</li>
        <li>性能安全优化</li>
        <!-- 以上都是毛毛雨 -->
        <li>VUE全家桶:vue-cli\vue\vue-router\vuex\vue
 element...</li>
        <li>vue和vuex的核心源码</li>
        <li>REACT全家桶:create-react-app、antd、antdpro、
react、react-dom、react-native、react-router-dom、redux、
react-redux、dva、redux-sage、mobx...</li>
        <li>REACT核心原理</li>
        <li>REDUX源码和中间件编写</li>
        <!-- 只有这些还不够,增添逼格 -->
        <li>webpack</li>
        <li>node和express</li>
        <li>type script</li>
        <li>...</li>
        天,知识点好多···
    </ul>
    <!-- import Js -->
    <script src="/11节点操作.js"></script>
</body>
</html>
let box=document.getElementById('box');

//标准浏览器(非IE6-8)中会把空格和换行当做文本节点处理
(childNodes包含所有节点)
// console.log(box.childNodes);

// 只想要元素节点(但是IE6-8下,使用children会把注释也当
做元素节点)
// console.log(box.children.length);

/* 
    children:获取指定上下文中,所有元素子节点
        @params
            context[element oblect]指定上下文元素信息
        @return
            [array]返回所有的元素子节点集合
    by ct on 20230216
*/
/* function children(context){
    //1.先获取所有的子节点
    let res=[],
        nodeList=context.childNodes;
    //2.循环遍历所有的子节点,找出元素子节点,存储到res中即可
    for(var i=0;i<nodeList.length;i++){
        var item=nodeList[i];
        item.nodeType===1?res.push(item):null;
    }
    return res;
} */
// console.log(children(box));//jquery中children的源码

//====================================
// console.log(box.firstChild);
// console.log(box.firstElementChild);

var fangqi=document.getElementById('fangqi');
// console.log(fangqi.previousSibling);
// console.log(fangqi.previousElementSibling);

//获取上一个哥哥元素节点
function prev(context){
    //先找自己的哥哥
    var pre =context.previousSibling;
    //如果哥哥不是元素,则找哥哥的哥哥,一直到找到的是元素
节点为止
    while(pre.nodeType!==1){
        pre=pre.previousSibling;
    }
    return pre;
}
console.log(prev(fangqi));

//jquery中提供一些方法供我们获取元素:children、prev、
next、prevAll、nextAll、sibling、siblings、index...
```

#### 12.在JS中动态增删改元素

`createElement 创建元素对象`

`createTextNode 创建文本对象`

`appendchild 把元素添加到容器的末尾`

`inserBefore 把元素添加到指定容器中指定元素的前面`
```
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>操作DOM</title>
    <style>
        .RED {
            color: red;
            background: blue;
        }
    </style>
</head>

<body>
    <div id="heihei">嘿嘿</div>
    <script>
        //动态创建一个div元素对象,把其赋给box
        let box = document.createElement('div');
        box.id = 'boxActive';
        box.style.width = '200px';
        box.style.height = '30px';
        box.className = 'RED';

        let text = document.createTextNode('哈哈');
        // console.dir(text);

        //添加:容器.appendchild(元素)
        box.appendChild(text);
        // document.body.appendChild(box);

        //放到指定元素前:容器.insertBefore([指定元素],
[新增元素])
        let heihei=document.getElementById('heihei');
        // heihei.parentNode.insertBefore(...)
        document.body.insertBefore(box,heihei);
    </script>
</body>

</html>
```
`cloneNode(true/false) 克隆元素或者节点`

`removeChild移除容器中的某个元素`
```
    <div class="box">
        <span>我是中国人1</span>
    </div>

    <script>
        let box1 = document.querySelector('.box');
        //克隆第一份(深克隆:子元素及后代都克隆)
        let box2 = box1.cloneNode(true);
        box2.querySelector('span').innerText='我是中国人2';
        //克隆第二份(浅克隆:只克隆子元素)
        let box3 = box1.cloneNode(false);
        box3.innerHTML="<span>我是中国人3</span>";

        document.body.appendChild(box2);
        document.body.appendChild(box3);

        //========================移除第二个元素
        document.body.removeChild(box2);
        </script>
```

#### 13.自定义属性

`setAttribute / getAttribute / removeAttribute 设置获取
移除元素的自定义属性信息(这种方式是把自定义属性放到元素结构上)`
```
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>自定义属性</title>
</head>

<body>
    <button>按钮1</button>
    <button>按钮2</button>
    <button>按钮3</button>
    <!-- import JS -->
    <script>
        var btnList = document.querySelectorAll('button');
        for (var i = 0; i < btnList.length; i++) {
            //设置自定义属性:元素对象.属性名=属性值(原理是向
元素对象对应的堆内存中添加了一个属性)
            // btnList[i].myIndex = i + 1;
            
            //设置自定义属性:基于set-attribute是把属性信息
写到了元素标签的结构上(在结构中可以看到),并没有放到元素对象
对应的堆内存中
            btnList[i].setAttribute('data-index',i+1);
            btnList[i].onclick = function () {
            
            //获取自定义属性:元素对象.属性名(原理是从堆内存
中获取到对应的属性值)
            //alert(this.myIndex);

            //基于get-attribute可以吧结构上存储的自定义属性
值获取
            alert(this.getAttribute('data-index'));
            }
        }
    </script>
</body>

</html>
```



//1-6index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>11111</title>
</head>
<body>
    <script src="js/6-ueryURLPqarameter.js">

    </script>
</body>
</html>

 

//1-math的方法
//  console.log(typeof (Math));//=>"object"
// console.dir(Math);
/*
 * Math={
 *   PI:3.141592653589793
 *   abs:function(){[native code]}
 *   ceil:function(){[native code]}
 *   ···
 * }
 * Math.abs();
 * Math.PI; 
 */

/* 
console.log(Math.abs(-12.5));//=>12.5
console.log(Math.abs(12));//=>12
console.log(Math.abs(0));//=>0
//不是数字类型的值:先基于Number()转换为数字再处理
console.log(Math.abs('-1'));//=>1
console.log(Math.abs('-1px'));//=>NaN
console.log(Math.abs(true));//=>1 
*/
/* 
console.log(Math.ceil(12));//=>12
console.log(Math.ceil(12.1));//=>13
console.log(Math.ceil(12.9));//=>13
console.log(Math.ceil(-12.1));//=>-12
console.log(Math.ceil(-12.9));//=>-12

console.log(Math.floor(12));//=>-12
console.log(Math.floor(12.1));//=>12
console.log(Math.floor(12.9));//=>12
console.log(Math.floor(-12.1));//=>-13
console.log(Math.floor(-12.9));//=>-13
 */
/* 
console.log(Math.round(12));//=>12
console.log(Math.round(12.1));//=>12
console.log(Math.round(12.5));//=>13
console.log(Math.round(12.9));//=>13
console.log(Math.round(-12.1));//=>-12
console.log(Math.round(-12.5));//=>-12(负数中 .5舍)
console.log(Math.round(-12.9));//=>-13
 */
/* 
console.log(Math.max(12,5,68,23,45,3,28));//=>68
console.log(Math.min(12,5,68,23,45,3,28));//=>3
 */
/* 
console.log(Math.sqrt(9));//=>3 
console.log(Math.sqrt(-9));//=>NaN  
console.log(Math.pow(2,10));//=>1024
 */

/* for (let i = 0; i <= 10; i++) {
    console.log(Math.random());
} */
/*
0.2351119504604302
0.8103880292045642
0.9153034803838505
··· 
 */

//获取1-10之间的随机整数
// console.log(Math.round(Math.random()*9+1));
/* for (let i = 0; i <= 10; i++) {
    let ran = Math.round(Math.random() * (30 - 25) + 25);
    console.log(ran);
} 
*/
//2-数组的方法
//  let ary=[12,23,34,45];
// console.log(typeof(ary));//=>object
// console.dir(ary);
/*
ary{
    0:12,
    1:23,
    2:34,
    3:45,
    length:4
} 
数字作为索引(key属性名)
length代表长度

ary[0]根据索引获取指定项的内容
ary.length 获取数组的长度
ary.length-1最后一项的索引
 */

/*
    push:向数组末尾增加内容
    参数:@params
        多个任意类型
    返回值:@return
        新增后数组的长度 
 */
/* let ary=[10,20];
let res=ary.push(30,'AA');
//基于原生JS操作键值对的方法,也可以向末尾追加一项新的内容
ary[ary.length]=40;
console.log(res,ary); //=>4 [10,20,30,'AA',40]
*/

/*
    unshift:向数组开始位置增加内容
    参数:@params
        多个任意类型
    返回值:@return
        新增后数组的长度
 */
/* let ary = [10, 20];
let res = ary.unshift(30, 'AA');
//基于原生ES6展开运算符,把原有的ary克隆一份,在新的
数组中创建第一项,其余的内容实用原始ary中的信息即可,
也算实现了向开始追加的效果
ary = [100, ...ary];
console.log(res, ary);//=>4 [30,'AA',10,20] */

/* shift:删除数组中的第一项
    参数:@params
    返回值:@return
        删除的那一项
*/
/* let ary=[10,20,30,40];
let res=ary.shift();
console.log(res,ary);//=> 10 [20,30,40]
//基于原生JS中的delete,把数组当做普通的对象,确实
可以删除某一项内容,但是不会影响数组本身的结构特点
(length长度不会跟着修改),真实项目中杜绝这样的删除使用
delete ary[0];
console.log(res,ary);//=>{1:30,2:40,length:3} */

/*
    pop:删除数组中的最后一项
    参数:@params
    返回值:@return 
    删除的那一项 
*/
/* let ary=[10,20,30,40];
let res=ary.pop();
console.log(res,ary);//=>40 [10,20,30]
//基于原生JS让数组长度删掉一位,默认删除最后一项
ary.length--;//ary.length = ary.length - 1;
console.log(res,ary);//=>40 [10,20] */

/*
    splice:实现数组的增加、删除、修改
    参数:@params
    n,m都是数字  从索引n开始删除m个元素
    返回值:@return 
        把删除的部分用新数组存储起来返回
*/
/* let ary = [10, 20, 30, 40, 50, 60, 70, 80, 90];
let res = ary.splice(2, 4);
console.log(res, ary);//=>[30,40,50,60] 
[10,20,70,80,90] */
//基于这种办法可以清空一个数组,把原始数组中的内容以新
数组存储起来(类似数组的克隆:把原始数组克隆一份一模一
样的给新数组)
/* ary.slice(0);
console.log(ary);//[10,20,70,80,90] */
//删除最后一项
/* 
ary.splice(ary.length - 1);
console.log(ary);//=>[10,20,70,80]
//删除第一项
ary.splice(0, 1);
console.log(ary);//=>[20,70,80]
*/

/*
    splice:实现数组的增加、修改
    参数:@params
        n,m,x 从索引n开始删除m个元素,用x占用删除的部分
        n,0,x 从索引n开始,一个都不删,把x放到索引n的前面
    返回值:@return 
        把删除的部分用新数组存储起来返回
*/
/* 
let ary = [10, 20, 30, 40, 50];
let res = ary.splice(1,2,'哈哈哈');
console.log(res, ary);//=>[20,30] [10,'哈哈哈',40,50]

//实现增加
ary.splice(3,0,'嘻嘻')
console.log(ary);//=>[10, '哈哈哈', 40, '嘻嘻', 
50]

//向数组末尾追加
ary.splice(ary.length,0,'AAA');
console.log(ary);//=>[10, '哈哈哈', 40, '嘻嘻', 
50, 'AAA']

//向数组开端追加
ary.splice(0,0,'BBB');
console.log(ary);//=>['BBB', 10, '哈哈哈', 40, 
'嘻嘻', 50, 'AAA'] 
*/
//=======================================
/*
    slice:实现数组的查询
    参数:@params
        n,m  都是数字 从索引n开始,找到索引为m
的地方(不包含m这一项)
    返回值:@return 
        把找到的内容以一个新数组的形式返回
 */
/* 
let ary=[10,20,30,40,50];
let res=ary.slice(-1,-3);
console.log(res);//=>[20,30]
 */

//m不写是找到末尾
// res=ary.slice(1);
// console.log(res);//=>[20,30,40,50]

//数组的克隆,参加0不写也可以
// res=ary.slice(0);
// console.log(res);//=>[10,20,30,40,50]

//思考: 
// 1.如果n、m是负数会怎么样?若n>m会怎么样?如果是
小数会怎么样?若是非有效数字会怎么样?若m或n的值比
最大索引都大会怎么样?
// 若n为负,则无论m是正或负,均为空字符串
// 若n为正,
// 2.这种克隆方式叫浅克隆,深克隆如何处理?

/*
    concat:实现数组拼接
    参数:@params
        多个任意类型值
    返回值:@return 
        拼接后的新数组(原来数组不变)
 */
/* 
let ary1=[1,2,3];
let ary2=[4,5,6];
let res=ary1.concat('QQQ',ary2);
console.log(res); 
*/

/*
    tostring:把数组转换为字符串
    参数:@params
    返回值:@return 
        转换后的字符串,每一项用逗号分隔(原来数组不变)
 */
/* 
let ary=[1,2,3];
let res=ary.toString();
console.log(res); //=>"1,2,3"
console.log([].toString());//=>""
console.log([12].toString());//=>"12" 
*/

/*
    join:把数组转换为字符串
    参数:@params
        指定的分隔符(字符串格式)
    返回值:@return 
        转换后的字符串(原来数组不变)
 */
/*
 let ary=[1,2,3];
// let res=ary.join('');
// console.log(res); //=>"123"
// let res=ary.join('|');
// console.log(res); //=>"1|2|3"
// let res=ary.join();
// console.log(res);
let res=ary.join('+');
console.log(res);
console.log(eval(res)); //=>eval把字符串变为JS表达式执行 
*/

/*
    indexOf / lastIndexOf:检测当前项在数组中第一次
或者最后一次出现位置的索引值(在IE6-8中不兼容)
    参数:@params
        要检索的这一项内容
    返回值:@return 
        这一项出现的位置索引值(数字),如果数组中没
有这一项,返回的结果是-1
    原来数组不变
*/
/* let ary = [1, 2, 3, 1, 2, 3];
console.log(ary.indexOf(2));//=>1
console.log(ary.lastIndexOf(2));//=>4

//验证ary中是否包含'哈哈哈'
if (ary.indexOf('哈哈哈') === -1){
    //不包含
}
//也可以直接使用ES6新提供的includes方法判断
if(ary.includes(3)){
    //包含:如果存在返回的是true
} */

/* 
    reverse:把数组倒过来排列
    参数:@params
    返回值:@return 
        排列后的新数组
    原来数组改变
*/
/* let ary = [12, 15, 9, 28, 10, 22];
ary.reverse();
console.log(ary);//=>[22, 10, 28, 9, 15, 12] */

/* 
    sort :实现数组的排序
    参数 :@params
        可以没有,也可以是个函数
    返回值 :@return 
        排列后的新数组
    原来数组改变
*/
// let ary = [4,7,5,8,3,6,1,9,2];
// ary.sort();
// console.log(ary);//=>[1, 2, 3, 4, 5, 6, 7, 8, 9]

//sort 方法中如果不传递参数,是无法处理10以上数字排序的
(它默认按照每一项第一个字符来排序,不是按照数值大小排的)
/* let ary = [12, 15, 9, 28, 10, 22];
ary.sort();
console.log(ary);//=>[10, 12, 15, 22, 28, 9] */

//实现多位数正常排序,需要给sort传递一个函数,函数中返回
a-b 实现升序,返回b-a 实现降序(? 需了解冒泡排序的机制)
/* let ary = [12, 15, 9, 28, 10, 22];
//ary.sort(function(a,b){return a-b});
//a和b是相邻的两项
ary.sort((a, b) => a - b);
console.log(ary);//=>[9, 10, 12, 15, 22, 28] 
*/

/* 
    forEach :遍历数组中的每一项内容
    参数 :@params
        回调函数
    返回值 :@return 

    原来数组改变
*/
let ary = [1, 5, 9, 6, 5, 12, 14];

/* //基于原生JS中的循环可以实现
for (let i = 0; i < ary.length; i++) {
    //i:当前循环这一项的索引
    //ary[i]:根据索引获取循环的这一项
    console.log('索引:' + i + '内容:' + ary[i]);
} */

ary.forEach((item, index) => {
    // 数组中有多少项,函数就会被默认执行多少次
    //每一次执行函数:item是数组中当前要操作的这一项,
index是当前项的索引
    console.log('索引:' + index + '内容:' + item);
});



//3-数组去重
//  let ary = [1, 2, 3, 1, 2, 1, 2, 3, 2, 1, 2, 3];
//=>[1,2,3]

/* 
方案一:
    循环原有数组中的每一项,每拿到一项都往新数组中添加
    添加之前验证新数组中是否存在这一项,不存在再添加
 */
/* let newAry = [];
for (let i = 0; i < ary.length; i++) {
    //循环获取原有数组中的每一项
    let item = ary[i];
    //验证新数组中是否存在这一项
    if (newAry.includes(item)) {
        //存在这一项,不再增加到新数组,继续下一轮循环即可
        continue;
    }
    //新数组中不存在这一项,我们加入到新数字即可
    newAry.push(item);
}
console.log(newAry); */
/* //方案一优化
let newAry = [];
ary.forEach(item => {
    if (newAry.includes(item)) return;
    newAry.push(item);
});
console.log(newAry); */
/*
方案二:
    先分别拿出数组中的每一项A
    用这一项A和它后边的每一项依次进行比较,如果遇到和
当前项A相同的,则在原来数组中把这一项移除掉

    不用includes/indexOf,保证兼容性
 */
/* var ary = [1, 2, 3, 1, 2, 1, 2, 3, 2, 1, 2, 3];
for (var i = 0; i < ary.length; i++) {
    //item:每一次循环拿出来的当前项
    //i:当前项索引
    var item = ary[i];
    
    //itemLast:当前项后边所有的内容(新数组)
    //var itemLast = ary.slice(i + 1); //创建数组耗性能

    //i+1:代表后一项
    //让当前项与后边的每一项进行比较(循环)
    for (var j = i + 1; j < ary.length; j++) {
        //compare:后边需要比较的每一项
        var compare = ary[j];
        //如果compare和item相等,说明这一项是重复的,把他删掉
        if (compare === item) {
            //j索引这一项要从数组中移除
            ary.splice(j, 1);
            //数组塌陷了:j后边的每一项索引都提前了一位,下
一次要比较还是j这个索引的内容
            j--;
        }
    }

}
console.log(ary); */
/* var ary = [1, 2, 3, 1, 2, 1, 2, 3, 2, 1, 2, 3];
for( var i=0;i<ary.length;i++){
    //第一轮:
    //i=0 item=1 拿到第一项
    //第二轮
    //i=1 item=2 拿到第二项
    var item=ary[i];
    for(var j=i+1;j<ary.length;j++){
        //j=1 compare=2 2!==1
        //j=2 compare=3 3!==1
        //j=3 compare=1 1===1 ary.splice(3,1);
[1, 2, 3, (1) 2, 1, 2, 3, 2, 1, 2, 3]
        var compare=ary[j];
        if(item===compare){
            ary.splice(j,1);
            j--;
        }
    }
}
console.log(ary); */
/* 
方案三:
 */
/* let ary = [1, 2, 3, 1, 2, 1, 2, 3, 2, 1, 2, 3];
//1.创建一个空对象
let obj = {};
//2.循环数组中的每一项,把每一项向对象中进行存储 =>
 item:item
for (let i = 0; i < ary.length; i++) {
    let item = ary[i];
    //3.存储之前进行判断:验证obj中是否存在这一项
    if (obj[item] !== undefined) {
        //已经存在这一项
        ary.splice(i, 1);
        i--;
        continue;

    }
    obj[item] = item;//obj[1]=1;···
}
console.log(ary); */
//基于splice实现删除性能不好:当前项被删后,后面每一
项的索引都要向前提一位,如果后面内容过多,定影响性能
/* 
let ary = [1, 2, 3, 1, 2, 1, 2, 3, 2, 1, 2, 3];
let obj = {};
for (let i = 0; i < ary.length; i++) {
    let item = ary[i];
    if (obj[item] !== undefined) {
        ary[i] = ary[ary.length - 1];
        ary.length--;
        i--;
        continue;

    }
    obj[item] = item;//obj[1]=1;···
}
console.log(ary); 
*/

/*
    unique:实现数组去重的方法
    @params
        ary[Array]要去重的数组
    @return
        [Array]去重后的数组
    by ct on 20230214
 */
/* function unique(ary) {
    let obj = {};
    for (let i = 0; i < ary.length; i++) {
        let item = ary[i];
        if (obj[item] !== undefined) {
            ary[i] = ary[ary.length - 1];
            ary.length--;
            i--;
            continue;
        }
        obj[item] = item;
    }
    return ary;
}
let aa = [1, 5, 6, 8, 12, 1, 2, 5, 6, 15, 47, 12, 47];
aa = unique(aa);
aa.sort((a, b) => a - b);
console.log(aa);//=>[1, 2, 5, 6, 8, 12, 15, 47] */

//正则
// let ary = [1, 5, 6, 8, 12, 1, 2, 5, 6, 15, 47, 12, 47];
// ary.sort((a, b) => a - b);
// let str = ary.join('@') + '@';
// let reg = /(\d+@)\1*/g;
// console.log(str.match(reg));
// ary = [];
// str.replace(reg, (n, m) => {
//     m = Number(m.slice(0, m.length - 1));
//     ary.push(m);
// });
// console.log(ary);//=>[1, 2, 5, 6, 8, 12, 15, 47]

//基于ES6的set(对应的Map)实现去重
let ary = [1, 5, 6, 8, 12, 1, 2, 5, 6, 15, 47, 12, 47];
ary = [...new Set(ary)];
console.log(ary);//=>[1, 5, 6, 8, 12, 2, 15, 47]






数组去重解析一

 数组去重解析二

数组去重解析三

 

 

// 4-字符串
/* let str = 'hahahahahah';
//循环输出字符串中的每一个字符
for(let i=0;i<str.length;i++){
    let char = str[i];
    console.log(char);
} 
*/

/* 
charAt:根据索引获取指定位置的字符
charCodeAt:获取指定字符的ASII码值(Unicode编码值)
@params
    n[number] 获取字符指定的索引
@return
    返回查找到的字符
    找不到返回的是空字符串㐊undefined,或者对应的编码值
 */
/* 
let str = 'hahahahahah'; 
console.log(str.charAt(0)); //=>'h'  
console.log(str[0]);   //=>'h'
console.log(str.charAt(100));  //=>''
console.log(str[100]);   //=>undefined

console.log(str.charCodeAt(0)); //=>104
console.log(String.fromCharCode(str.charCodeAt(0)));
//=>'h' 
 */

/* 
都是为了实现字符串截取(在原来字符串查找到自己想要的)
substr(n,m):从索引n开始截取m个字符,m不写截取到末尾
(其他的方法也是)
substring(n,m):从索引n开始找到索引m处(不包含m)
slice(n,m):和substring一样,都是找到索引m处,但
slice可以支持负数作为索引,其余两个方法不可以
 */
/* 
let str = 'hahahahahaha'; 
console.log(str.substr(3,7));//=>'ahahaha'
console.log(str.substring(3,7));//=>'ahah'
console.log(str.substr(3));//=>'ahahahaha' 截取
到末尾
console.log(str.substring(3,100));//=>'ahahahaha'
 截取到末尾(超过索引的也只截取到末尾)

console.log(str.substring(3,7));//=>'ahah'
console.log(str.slice(3,7));
console.log(str.substring(-7,-3));//=>'' substring
不支持负数索引
console.log(str.slice(-7,-3));//=>'nqit' slice支持
负数索引  快捷查找:负数索引,按照STR.length+负索引的
方式找  =>slice(12-7,12-3) =>slice(5,9) =>ahah
 */

/*
验证字符是否存在
    indexOf(x,y):获取x第一次出现位置的索引,y是控制
查找的起始位置索引
    lastIndexOf(x):最后一次出现位置的索引
    =>没有这个字符,返回的结果是-1
 */
/* 
let str = 'hahahahahaha'; 
console.log(str.indexOf('h'));//=>0
console.log(str.lastIndexOf('h'));//=>10
console.log(str.indexOf('!'));//=>-1  不存在返回-1
if(str.indexOf('!')===-1){
    //字符串中不包含!这个字符
}

console.log(str.indexOf('aha'));//=>1 验证整体第一
次出现的位置,返回的索引是第一个字符所在位置的索引值
console.log(str.indexOf('ahan'));//=>-1
console.log(str.indexOf('ha',5));//=>6 查找索引5
及之后的字符串中,ha第一次出现的位置索引

if(!str.includes('!')){
    console.log('当前字符串不包含!');
} 
*/

/*
字符串中字母的大小写转换
    toUpperCase():转大写
    toLowerCase():转小写
 */
/* 
let str = 'Hahahahahaha';
str = str.toUpperCase();
console.log(str);//=>'HAHAHAHAHAHA'
str = str.toLowerCase();
console.log(str);//=>'hahahahahaha'
//实现首字母大写
str = str.substr(0, 1).toUpperCase() + 
str.substr(1);
console.log(str);//=>Hahahahahaha 
 */

/*
    split([分隔符]):把字符串按照指定的分隔符拆分成
数组(和数组里的join相对应)
    split支持传递正则表达式
 */
//需求:把|分隔符变为,分隔符
/*
 let str = 'music|movie|eat|sport';
let ary=str.split('|');//=>['music', 'movie', 
'eat', 'sport']
console.log(ary);
str=ary.toString();
console.log(str);//=>music,movie,eat,sport
str=ary.join(',');
console.log(str);//=>music,movie,eat,sport 
 */

/*
    replace(老字符,新字符):实现字符串的替换
(经常伴随着正则使用)
 */
let str='哈喽!你好!是吧?';
/* str=str.replace('!','+');
console.log(str);//=>哈喽+你好!是吧? 在不使用
正则表达式的情况下,执行一次replace只能替换一次字符 */ 
str=str.replace(/!/g,'-');
console.log(str);//=>哈喽-你好-是吧?


// 5-时间
// let time = '2023-2-14 19:45:45';
//=>变为自己需要呈现的格式,例如:
//"2023年2月14日 19点45分45秒"
//"2023年2月14日"
//"2/14 19:45"
//···

//方案一:
/*
    let time = '2023-2-14 19:45:45';
    time = time.replace('-', '年').replace('-', '月')
.replace(' ', '日 ').replace(':', '时')
.replace(':', '分') + '秒';
    console.log(time);//=>2023年2月14日 19时45分45秒
 */

//方案二:获取年月日时分秒这几个值,按照所想拼出效果

//不足十位补零
/* 
let addZero = val => {
    if (val.length < 2) {
        val = '0' + val;
    }
    return val;
};
 */
/* 
let addZero = val => val.length < 2 ? '0' + val : val;
let time = '2023-2-14 19:45:45';
let ary = time.split(/(?: |-|:)/g);//=>['2023', '2',
 '14', '19', '45', '45']
time = ary[0] + '年' + addZero(ary[1]) + '月' + 
addZero(ary[2]) + '日';
console.log(time);//=>2023年02月14日 
*/

//获取值的方法:基于split一项项拆分
/*
let time = '2023-2-14 19:45:45';
let n = time.split(' ');//=>["2023-2-14" ,"19:45:45"]
let m = n[0].split('-')//=>["2023","2","14"]
let x = n[1].split(':');//=>["19","45","45"]
console.log(x);
*/

//获取值的方法:基于indexOf获取指定符号索引,基于
substring一点点截取
/* 
let time = '2023-2-14 19:45:45';
let n = time.indexOf('-');
let m = time.lastIndexOf('-');
let x = time.indexOf(' ');
let y = time.indexOf(':');
let z = time.lastIndexOf(':');
let year = time.substring(0, n);
let month = time.substring(n + 1, m);
let day = time.substring(m + 1, x);
console.log(year, month, day); */
// 6-queryURLParameter
// let url = 'http://www.zhufengpeixun.cn/index.html?lx=1&name=zhufeng&teacher=aaa#box';
/*
    结果:{
        lx:1,
        name:'zhufeng',
        teacher:'aaa',
        HASH:'box'
    }
 */

/* //1.获取问号或者井号后边的值
let askIndex = url.indexOf('?');
let wellIndex = url.indexOf('#');
let askText = url.substring(askIndex + 1, wellIndex);
let wellText = url.substring(wellIndex + 1);
console.log(askText, wellText);
// askText="lx=1&name=zhufeng&teacher=aaa" 
// wellText="box"
//2.问号后边值的详细处理
let result = {};
let askAry = askText.split('&');
console.log(askAry);
//=>['lx=1', 'name=zhufeng', 'teacher=aaa']
askAry.forEach(item => {
    //item:当前从数组中循环的这一项
    let n = item.split('=');
    console.log(n);
    // ['lx', '1']
    // ['name', 'zhufeng']
    // ['teacher', 'aaa']
    let key = n[0];
    let value = n[1];
    result[key] = value;
});
result['HASH'] = wellText;
console.log(result);
//=>{lx: '1', name: 'zhufeng', teacher: 'aaa', 
HASH: 'box'} */


/*
    queryURLParams:获取URL地址中间问号传参的信息和哈希值
    @params
        URL[string]要解析的url字符串
    @return
        [object]包含参数和哈希值信息的对象
    by ct on 20230214
 */

/* function queryURLParams(url) {
    //1.获取?和#后边的信息
    let askIn = url.indexOf('?'),
        wellIn = url.indexOf('#'),
        askText = '',
        wellText = '';
    //#不存在
    wellIn === -1 ? wellIn = url.length : null;
    //?存在
    askIn >= 0 ? askText = url.substring(askIn + 1,
 wellIn) : null;
    wellText = url.substring(wellIn + 1);
    //2.获取每部分信息
    let result = {};
    wellText !== '' ? result['HASH'] = wellText : null;
    if (askText !== '') {
        let ary = askText.split('&');
        ary.forEach(item => {
            let itemAry = item.split('=');
            result[itemAry[0]] = itemAry[1];
        });
    }
    return result;
} 
*/


//基于正则封装、完美
function queryURLParams(url) {
    let result = {},
        reg1 = /([^?=&#]+)=([^?=&#]+)/g;
        reg2 = /#([^?=&#]+)/;
        url.replace(reg1, (n, x, y) => result[x] = y);
        url.replace(reg2, (n, x) => result['HASH'] = x);
    return result;
}


let url = 'http://www.zhufengpeixun.cn/index.html?lx=1&name=zhufeng&teacher=aaa#box';
let paramsObj = queryURLParams(url);
console.log(paramsObj);
//7-验证码
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>简单的验证码</title>
</head>

<body>
    <input type="text" id="codeInp">
    <br>
    <span id="codeBox">aaaa</span>
    <button id="changeCode">看不清,换一张</button>
    <!-- import Js -->
    <script>
        let codeInp = document.getElementById('codeInp'),
            codeBox = document.getElementById('codeBox'),
            changeCode = document.getElementById('changeCode');

        /*
            queryCode:获取到四位随机验证码,然后放到指定的盒子中
                @params
                @return
                by ct on 20230214 
         */
        function queryCode() {
            let area = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz
0123456789";
            let result = "";
            for (let i = 0; i < 4; i++) {
                //每一次循环都获取一个随机的数字索引
                let ran = Math.round(Math.random() * 61);
                //再根据获取的索引从范围字符串中找到对应的字符,
把找到的字符拼接到最后的结果中
                result += area.charAt(ran);
            }
            //放到盒子里
            codeBox.innerHTML = result;
        }

        //第一次加载页面需要执行方法,让其显示在页面中
        queryCode();
        //点击看不清按钮,需要重新执行方法生成新的验证码
        changeCode.onclick = queryCode;
        //文本框失去焦点的时候:验证用户输入法人内容和验证
码是否相同,给予相关的提示,如果不一样需要重新生成验证码
        //onblur:文本框失去焦点事件
        codeInp.onblur = function () {
            //获取用户和验证码内容(表单元素.value / 非表单
元素.innerHTML 获取内容)
            let val = codeInp.value,
                code = codeBox.innerHTML;
            //不区分大小写的验证(都转小写)
            if (val.toLowerCase() === code.toLowerCase()) {
                alert('温馨提示:验证码输入成功!');
            } else {
                alert('温馨提示:验证码输入错误,请重新输入!');
                codeInp.value = '';
                //重新生成验证码
                queryCode();
            }
        }
    </script>
</body>

</html>
//8-小时钟
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>小时钟</title>
    <!-- import css -->
    <style>
        * {
            margin: 0;
            padding: 0;
        }

        #clockBox {
            position: absolute;
            right: 0;
            top: 0;
            padding: 0 15px;
            line-height: 50px;
            font-size: 20px;
            color: black;
            /* 设置背景渐变色 */
            /* background:lightblue ; */
            background: -webkit-linear-gradient
(top left, lightcoral, lightcyan);
        }
    </style>
</head>

<body>
    <div id="clockBox">
        2023年02月15日 星期三 16:24:01
    </div>
    <!-- import JS -->
    <script>
        let clockBox = document.getElementById
('clockBox');
        /* 
            addZero:不足十补领
                @params
                    val需要处理的值
                @return
                    处理后的结果
            by ct on 20230215
        */

        function addZero(val) {
            val = Number(val);
            return val < 10 ? '0' + val : val;
        }
        /* 
            queryDate:获取当前日期,把其转换为想要的格式
                @params
                @return
            by ct on 20230215
         */
        function queryDate() {
            //1.获取当前日期及详细信息
            let time = new Date(),
                year = time.getFullYear(),
                month = time.getMonth() + 1,
                day = time.getDate(),
                week = time.getDay(),
                hours = time.getHours(),
                minutes = time.getMinutes(),
                seconds = time.getSeconds();
            //2.拼凑成想要的字符串

            let result = year + "年" + addZero(month)
 + "月" + addZero(day) + "日";
            let weekAry = ['日', '一', '二', '三', '四',
 '五', '六'];
            result += " 星期" + weekAry[week] + " ";
            result += addZero(hours) + ":" +
 addZero(minutes) + ":" + addZero(seconds);
            //3.把处理好的结果放盒子里
            clockBox.innerHTML = result;
        }
        //加载页面执行方法
        queryDate();

        //定时器控制运动:设置一个setInterval定时器
(到达指定时间做对应的事的东西就是定时器),每隔1000ms
执行queryDate方法
        setInterval(queryDate, 1000);
    </script>
</body>

</html>
//9-时间格式化
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>时间格式化</title>
</head>

<body>
    <script>
        let addZero = val => {
            val = Number(val);
            return val < 10 ? '0' + val : val;
        }

        /* 
            字符串处理
        */
        /* function formatTime(time) {
            //1.获取年月日星期
            // let ary=time.split(/(?: |-|:)/g);
            let ary = time.split(' ');
            let aryLeft = ary[0].split('-'),
                aryRight = ary[1].split(':');
            ary = aryLeft.concat(aryRight);
            //=>['2023', '2', '15', '12', '0', '0']
            //2.拼接为想用的格式
            let result = ary[0] + "年" + addZero(ary[1]) 
+ "月" + addZero(ary[2]) + "日";

            result += " " + addZero(ary[3]) + ":"
 + addZero(ary[4]) + ":" + addZero(ary[5]);
            return result;
        } 
        let time = '2023-2-15 12:0:0';
        //=>"2023年02月15日 12:00:00"
        time = formatTime(time);
        console.log(time);
        //=>2023年02月15日 12:00:00*/

        /* 
            基于日期对象处理
        */
        /* function formatTime(time) {
            //1.把时间字符串变为标准日起对象

            // time = time.replace(/-/g,'/');
            time = time.replace('-', '/');
            time = time.replace('-', '/');
            time = new Date(time);
            //2.基于方法获取年月日等信息
            let year = time.getFullYear(),
                month = addZero(time.getMonth() + 1),
                day = addZero(time.getDate()),
                hours = addZero(time.getHours()),
                minutes = addZero(time.getMinutes()),
                seconds = addZero(time.getSeconds());
            //3.返回想要的结果
            return year+"年"+month+"月"+day+"日"+hours+"时"+minutes+"分"+
seconds+"秒";
            
        } 
        let time = '2023-2-15 12:0:0';
        //=>"2023年02月15日 12:00:00"
        time = formatTime(time);
        console.log(time);
        //=>2023年02月15日 12:00:00*/

        /* 
            封装一套公共的时间字符串格式化处理函数
        */
        String.prototype.formatTime = function 
formatTime(template) {
            typeof templete === 'undefined' ? 
templete = "{0}年{1}月{2}日 {3}:{4}:{5}" : null;
            //this:要处理的字符串
            let matchAry = this.match(/\d+/g);
            //模板和数据的渲染(引擎机制)
            templete = templete.replace(/\{(\d+)\}/g, 
(x, y) => {
                let val = matchAry[y] || '00';
                val.length<2?val='0'+val:null;
                return val;
            });
            return templete;
        };

        let time = '2023-2-15 12:0:0';
        //=>"2023年02月15日 12:00:00"
        console.log(time.formatTime());//传一个模板
        //=>2023年02月15日 12:00:00

    </script>
</body>

</html>
//10-获取元素
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>获取元素</title>
</head>
<body>
    <!-- <div class="tabBox" id="tabBox">
        <ul class="tab" id="tab">
            <li>第1个页卡</li>
            <li>第2个页卡</li>
            <li>第3个页卡</li>
        </ul>
        <div>
            第1个要展示的内容
            <ul class="news">
                <li>热门新闻1</li>
                <li>热门新闻2</li>
                <li>热门新闻3</li>
                <li>热门新闻4</li>
                <li>热门新闻5</li>
            </ul>
        </div>
        <div>
            第2个要展示的内容
            <div class="detail"></div>
        </div>
        <div>第3个要展示的内容</div>
    </div> -->
    <div class="formBox">
        性别:
        <!-- name在表单中是用来分组的 -->
        <input type="radio" name="sex" value="男"  checked>男
        <input type="radio" name="sex" value="女" >女
        <input type="radio" name="sex" value="未知">未知


        <button id="submit">点击获取选中的是谁?</button>
    </div>
    <!-- import js -->
    <script src="/10获取元素.html"></script>
</body>
</html>

//10获取元素js
// let tabBox=document.getElementById('tabBox');

//基于getElementByTagName / getElementsByClassName
获取到的元素集合,想要操作某个元素需要在集合中根据索引取
出来才可以使用
// let tabBox = document.getElementsByClassName
('tabBox')[0];

//querySelector获取的是一个元素对象,哪怕页面中有多个
符合的,也只获取第一个
//querySelectorAll获取的是一个集合,那怕只有一个符合,
也是一个集合,集合中只有一项
// let tabBox = document.querySelector('.tabBox');

//getElementsByTagName是获取指定上下文后代中所有的标签
名为N的元素集合
// let navList=tabBox.getElementsByTagName('li');
// let navList=tab.getElementsByTagName('li');

// let navList=tabBox.querySelectorAll('.tab li');
// let navList = document.querySelectorAll('.tab li');
// let divList = document.querySelectorAll('.tabBox>div');

// jquery:一个操作DOM元素的类库
// var $navlist=$('.tab li');
// var $divList=$('.tabBox>div');
// console.log($navList,$divList);

//===========================
var sexList=document.getElementsByName('sex');
var submit=document.getElementById('submit');

// var sexList = document.querySelectorAll('[name=sex]');
// var submit = document.querySelector('#submit');
console.log(sexList,submit);

submit.onclick=function(){
    var res=null;
    for(var i=0;i<sexList.length;i++){
        var item=sexList[i];
        if(item.checked){
            //被选中
            res=item.value;
            break;
        }
    }
    alert(res);
}
//11节点操作
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>节点操作</title>
</head>
<body>
    <ul id="box">
        <!-- 课程大纲 -->
        <li>GIT和NPM操作</li>
        <li>面向对象好原型:研究插件源码,自己写插件</li>
        <li>闭包作用域:堆栈内存处理</li>
        <li id="fangqi">ES6从入门开始</li>
        <li>同步异步编程及核心:微任务、宏任务、事件循环</li>
        <li>DOM及事件模型</li>
        <li>JQuery及源码分析</li>
        <li>设计模式:发布订阅、单例、Promise、PromiseA+</li>
        若觉得上边难,下边更难
        <li>AJAX及跨域解决方案:封装一款牛*的AJAX库</li>
        <li>一入http深似海</li>
        <li>性能安全优化</li>
        <!-- 以上都是毛毛雨 -->
        <li>VUE全家桶:vue-cli\vue\vue-router\vuex\vue
 element...</li>
        <li>vue和vuex的核心源码</li>
        <li>REACT全家桶:create-react-app、antd、antdpro
、react、react-dom、react-native、react-router-dom、
redux、react-redux、dva、redux-sage、mobx...</li>
        <li>REACT核心原理</li>
        <li>REDUX源码和中间件编写</li>
        <!-- 只有这些还不够,增添逼格 -->
        <li>webpack</li>
        <li>node和express</li>
        <li>type script</li>
        <li>...</li>
        天,知识点好多···
    </ul>
    <!-- import Js -->
    <script src="/11节点操作.js"></script>
</body>
</html>

//节点操作js
let box=document.getElementById('box');

//标准浏览器(非IE6-8)中会把空格和换行当做文本节点处理
(childNodes包含所有节点)
// console.log(box.childNodes);

// 只想要元素节点(但是IE6-8下,使用children会把注释也
当做元素节点)
// console.log(box.children.length);

/* 
    children:获取指定上下文中,所有元素子节点
        @params
            context[element oblect]指定上下文元素信息
        @return
            [array]返回所有的元素子节点集合
    by ct on 20230216
*/
/* function children(context){
    //1.先获取所有的子节点
    let res=[],
        nodeList=context.childNodes;
    //2.循环遍历所有的子节点,找出元素子节点,存储到res中即可
    for(var i=0;i<nodeList.length;i++){
        var item=nodeList[i];
        item.nodeType===1?res.push(item):null;
    }
    return res;
} */
// console.log(children(box));//jquery中children的源码

//====================================
// console.log(box.firstChild);
// console.log(box.firstElementChild);

var fangqi=document.getElementById('fangqi');
// console.log(fangqi.previousSibling);
// console.log(fangqi.previousElementSibling);

//获取上一个哥哥元素节点
function prev(context){
    //先找自己的哥哥
    var pre =context.previousSibling;
    //如果哥哥不是元素,则找哥哥的哥哥,一直到找到的是
元素节点为止
    while(pre.nodeType!==1){
        pre=pre.previousSibling;
    }
    return pre;
}
console.log(prev(fangqi));

//jquery中提供一些方法供我们获取元素:children、prev、
next、prevAll、nextAll、sibling、siblings、index...
//12DOM动态操作
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>操作DOM</title>
    <style>
        .RED {
            color: red;
            background: blue;
        }

        .box {
            margin-top: 10px;
            width: 200px;
            height: 100px;
            background-color: lightblue;
        }

        .box span {
            color: red;
            font-size: 18px;
        }
    </style>
</head>

<body>
    <!-- <div id="heihei">嘿嘿</div> -->
    <div class="box">
        <span>我是中国人1</span>
    </div>

    <script>
        let box1 = document.querySelector('.box');
        //克隆第一份(深克隆:子元素及后代都克隆)
        let box2 = box1.cloneNode(true);
        box2.querySelector('span').innerText='我是中国人2';
        //克隆第二份(浅克隆:只克隆子元素)
        let box3 = box1.cloneNode(false);
        box3.innerHTML="<span>我是中国人3</span>";

        document.body.appendChild(box2);
        document.body.appendChild(box3);

        //========================移除第二个元素
        document.body.removeChild(box2);
    </script>
    <script>
        /* //动态创建一个div元素对象,把其赋给box
        let box = document.createElement('div');
        box.id = 'boxActive';
        box.style.width = '200px';
        box.style.height = '30px';
        box.className = 'RED';

        let text = document.createTextNode('哈哈');
        // console.dir(text);

        //添加:容器.appendchild(元素)
        box.appendChild(text);
        // document.body.appendChild(box);

        //放到指定元素前:容器.insertBefore([指定元素],[新增元素])
        let heihei=document.getElementById('heihei');
        // heihei.parentNode.insertBefore(...)
        document.body.insertBefore(box,heihei); */
    </script>
</body>

</html>
//13自定义属性
<!DOCTYPE html>
<html>

<head>
    <meta charset="UTF-8">
    <title>自定义属性</title>
</head>

<body>
    <button>按钮1</button>
    <button>按钮2</button>
    <button>按钮3</button>
    <!-- import JS -->
    <script>
        var btnList = document.querySelectorAll('button');
        for (var i = 0; i < btnList.length; i++) {
            //设置自定义属性:元素对象.属性名=属性值
(原理是向元素对象对应的堆内存中添加了一个属性)
            // btnList[i].myIndex = i + 1;

            //设置自定义属性:基于set-attribute是把
属性信息写到了元素标签的结构上(在结构中可以看到),并
没有放到元素对象对应的堆内存中
            btnList[i].setAttribute('data-index',i+1);
            btnList[i].onclick = function () {
                
            //获取自定义属性:元素对象.属性名(原理是从
堆内存中获取到对应的属性值)
            //alert(this.myIndex);

            //基于get-attribute可以吧结构上存储的自定义
属性值获取
            alert(this.getAttribute('data-index'));
            }
        }
    </script>
</body>

</html>

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值