js知识梳理十一

正则应用

1
2
3
4
5
6
7
8
let str = '54389',
ary = ['零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌', '玖'];
str = str.replace(/\d/g, item => {
//=>item =>arg[0] =>正则每一次捕获的内容 5/4/3/8/9
//=>把捕获的数字做为索引,到ARY中找到对应的汉字,用找到的结果替换当前捕获的内容
return ary[item];
});
console.log(str);
1
2
3
4
5
6
7
8
9
10
//30. 在javascript对象上定义一个repeatify函数,这个函数接受一个整数参数,来明确子字符串需要重复几次,这个函数要求字符串重复指定的次数,比如:’abc’.repeatify(3); //=>”abcabcabc”
String.prototype.repeatify = function repeatify(n = 1) {
//=>this:需要处理的字符串
let result = '';
for (let i = 0; i < n; i++) {
result += this;
}
return result;
};
console.log('abc'.repeatify());
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
//31. `var str='hello<img src="haha.png" alt="哈哈"/>world';`正确匹配输出’hello[哈哈]world’

let str = 'hello<img alt="哈哈" src="haha.png"/>world<img src="xiee.png" alt="邪恶"/>',
reg = /<img(?:[^<>]*alt="([\u4e00-\u9fa5]*)")\/>/g;
str = str.replace(reg, (...arg) => {
return `[${arg[1]}]`;
});
console.log(str);

----------------------------------------------------------------------------------

let str = 'hello<img alt="哈哈" src="haha.png"/>world<img src="xiee.png" alt="邪恶"/>',
reg = /<img([^<>]*)\/>/g;
str = str.replace(reg, (...arg) => {
let val = arg[1],
regVal = /alt=("|')([\u4e00-\u9fa5]*)\1/,
flag = regVal.test(val);
if (flag) {
val = regVal.exec(val)[2] || '';
return `[${val}]`;
}
return '';
});
console.log(str);
1
2
3
4
5
6
7
8
9
10
11
12
13
// 一个url 后面好多key-value 如localhost?key=val&key2=val2&key3=val3 封装一个函数 getParam(‘key’) 通过key获得相应等号后面的值.
let getParam = function (attr) {
//=>先把URL问号后面的值获取到
let str = 'localhost?name=zhufeng&year=9&teacher=zxt',
obj = {},
reg = /([^?&=#]+)=([^?&=#]+)/g;
str.replace(reg, (...arg) => {
let [, key, value] = arg;
obj[key] = value;
});
return obj[attr];
};
console.log(getParam('xxx'));
1
2
3
4
5
6
7
/*
写出完整的验证函数
> 1)长度不能小于6位
> 2)首字母必须是字母
> 3)合法字符只能是数字、字母、下划线
*/
let reg = /^[a-zA-Z]\w{5,}$/;
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
// 获取字符串中出现次数最多的字符及出现的次数
let str = 'zhufengpeixunzhouxiaotian';
/*
* 思路一:获取字符串中的每一个字母,然后以对象键值对的方式存储起来(属性名是字符,属性值是出现的次数)
*/
//1.获取每一个字符出现的次数,以及出现的最大次数
let obj = {},
max = 1,
result = [];
str.replace(/./g, char => {
if (obj.hasOwnProperty(char)) {
obj[char]++;
if (obj[char] > max) {
max = obj[char];
}
return;
}
obj[char] = 1;
});
//2.获取和MAX相匹配次数的字符
for (let char in obj) {
if (obj.hasOwnProperty(char)) {
if (obj[char] === max) {
result.push(char);
}
}
}
console.log(`最多出现的次数是:${max} 次,对应的字符有:${result}`);

/*
* 思路二:先把字符串中的每一个字符变为数组中的每一项,给数组排序,在变为字符串(相同的字符挨着),在基于正则捕获替换
*/
let max = 1;
str = str.split('').sort().join('');//=>'aaeefghhiiinnnooptuuuxxzz'
str = str.replace(/(.)\1*/g, (...arg) => {
let [value, char] = arg,
len = value.length;
len > max ? max = len : null;
return `${char}{${len}}`;
});
// console.log(str);//=>'a{2}e{2}f{1}g{1}h{2}i{3}n{3}o{2}p{1}t{1}u{3}x{2}z{2}'
// let reg =/([^\d{}])\{"+max+"\}/g;//=>字面创建正则的方式,正则中的每一个字符都是元字符,不能实现把一个变量的值作为正则一部分的需求
let reg = new RegExp('([^\\d{}])\\{' + max + '\\}', 'g');
str.replace(reg, (...arg) => {
console.log(arg[1]);
});

同步异步编程

JS中的同步编程和异步编程

  • 同步编程:任务是按照顺序依次处理,当前这件事没有彻底做完,下一件事是执行不了的
  • 异步编程:当前这件事没有彻底做完,需要等待一段时间才能继续处理,此时我们不等,继续执行下面的任务,当后面的任务完成后,再去把没有彻底完成的事情完成
    JS中的异步编程
  • 所有的事件绑定都是异步编程 xxx.onclick=function(){}
  • 所有的定时器都是异步编程 setTimeout(function(){},1000)
  • AJAX中一般都使用异步编程处理
  • 回调函数也算是异步编程

浏览器是如何规划同步异步机制的

  1. 浏览器是多线程的,JS是单线程的(浏览器只给JS执行分配一个线程):单线程的特点就是一次只能处理一件事情

    • 进程:每一个应用程序都可以理解为一个进程(浏览器打开一个页面,就相当于开辟一个进程),在一个程序中(进程中)我们经常会同时干很多事情,此时我们可以分配多个线程去同时完成多项任务
  2. JS在单线程中实现异步的机制,主要依赖于浏览器的任务队列完成的。浏览器中有两个任务队列(主任务队列、等待任务队列)

Promise

它是ES6中新增加的类 (new Promise),目的是为了管理JS中的异步编程的,所以我们也把它称为“Promise设计模式”

  • 三个状态:pending(准备:初始化成功,开始执行异步的任务)\fulfilled(成功)\rejected(失败)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
new Promise(() => {
//=>执行一个异步的任务(new Promise的时候,创建Promise的一个实例,立即会把当前函数体中的异步操作执行) =>“Promise是同步的,它可以管理异步操作”
setTimeout(() => {

}, 1000);
console.log(1);//=>先输出1
}).then();
console.log(2);//=>再输出2
------------------------------------------------
new Promise((resolve, reject) => {
//=>resolve:当异步操作执行成功,我们执行resolve方法
//=>reject:当异步操作执行失败,我们执行reject方法
setTimeout(() => {
resolve(100);
}, 1000);
}).then((res) => {
//=>第一个传递的函数是resolve
console.log('ok', res);
}, () => {
//=>第二个传递的函数是reject
console.log('no');
});

js动画

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/*==ANIMATE动画库==*/
~function () {
//=>准备操作CSS样式的方法 GET-CSS/SET-CSS/SET-GROUP-CSS/CSS
let utils = (function () {
//=>获取样式
let getCss = (ele, attr) => {
let val = null,
reg = /^-?\d+(\.\d+)?(px|rem|em)?$/;
if ('getComputedStyle' in window) {
val = window.getComputedStyle(ele)[attr];
if (reg.test(val)) {
val = parseFloat(val);
}
}
return val;
};

//=>设置样式
let setCss = (ele, attr, value) => {
if (!isNaN(value)) {
if (!/^(opacity|zIndex)$/.test(attr)) {
value += 'px';
}
}
ele['style'][attr] = value;
};

//=>批量设置样式
let setGroupCss = (ele, options) => {
for (let attr in options) {
if (options.hasOwnProperty(attr)) {
setCss(ele, attr, options[attr]);
}
}
};

//=>合并为一个
let css = (...arg) => {
let len = arg.length,
fn = getCss;
if (len >= 3) {
fn = setCss;
}
if (len === 2 && typeof arg[1] === 'object') {
fn = setGroupCss;
}
return fn(...arg);
};

return {css}
})();

//=>EFFECT:准备运动的公式
let effect = {
Linear: (t, b, c, d) => t / d * c + b
};

//=>封装动画库
window.animate = function (ele, target = {}, duration = 1000, callback = new Function()) {
//=>不传递CALL-BACK,让其默认为一个空函数(回调函数:当动画结束后做什么事,都放到回调函数完成即可)
if (typeof duration === 'function') {
//=>我们有四个形参,但是传递的时候只传递三个,最后一个回调函数传递给duration这个参数了,我们需要改一下参数的值
callback = duration;
duration = 1000;
}

//1.基于TARGET计算出BEGIN/CHANGE
let begin = {},
change = {},
time = 0;
for (let attr in target) {
if (target.hasOwnProperty(attr)) {
begin[attr] = utils.css(ele, attr);
change[attr] = target[attr] - begin[attr];
}
}

//2.实现动画
clearInterval(ele.animteTimer);//=>在给当前元素设置新的动画之前,先清空原有正在运行的动画(防止多动画共存,把动画的返回值赋值给当前元素的自定义属性,这样只要元素不变,我们不管啥时候在哪执行都可以清除元素的动画)
ele.animteTimer = setInterval(() => {
time += 17;
//=>边界判断
if (time >= duration) {
utils.css(ele, target);
clearInterval(ele.animteTimer);

callback.call(ele);//=>动画完成后执行CALL-BACK(并且让回调函数中的THIS是当前操作的元素本身)
return;
}
//=>依托TARGET计算出每个方向的当前位置
let cur = {};
for (let attr in target) {
if (target.hasOwnProperty(attr)) {
cur[attr] = effect.Linear(time, begin[attr], change[attr], duration);
}
}
utils.css(ele, cur);
}, 17);
};
}();

动画函数封装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
//=>UTILS操作CSS工具库
let utils = (function () {
//=>获取样式
let getCss = (ele, attr) => {
let val = null,
reg = /^-?\d+(\.\d+)?(px|rem|em)?$/;
if ('getComputedStyle' in window) {
val = window.getComputedStyle(ele)[attr];
if (reg.test(val)) {
val = parseFloat(val);
}
}
return val;
};

//=>设置样式
let setCss = (ele, attr, value) => {
if (!isNaN(value)) {
if (!/^(opacity|zIndex)$/.test(attr)) {
value += 'px';
}
}
ele['style'][attr] = value;
};

//=>批量设置样式
let setGroupCss = (ele, options) => {
for (let attr in options) {
if (options.hasOwnProperty(attr)) {
setCss(ele, attr, options[attr]);
}
}
};

//=>合并为一个
let css = (...arg) => {
let len = arg.length,
fn = getCss;
if (len >= 3) {
fn = setCss;
}
if (len === 2 && typeof arg[1] === 'object') {
fn = setGroupCss;
}
return fn(...arg);
};

//=>EACH:遍历对象、数组、类数组
let each = (obj, callback) => {
if ('length' in obj) {
for (let i = 0; i < obj.length; i++) {
let item = obj[i],
res = callback && callback.call(item, i, item);
if (res === false) {
break;
}
}
return;
}
for (let attr in obj) {
if (obj.hasOwnProperty(attr)) {
let item = obj[attr],
res = callback && callback.call(item, attr, item);
if (res === false) {
break;
}
}
}
};

return {css, each}
})();

//=>ANIMATE动画库
~function () {
//=>匀速运动公式
let effect = {
Linear: (t, b, c, d) => t / d * c + b
};

//=>开始运动
window.animate = function animate(ele, target, duration = 1000, callback) {
//=>参数处理(传递三个值,第三个值是函数,其实本身想要代表的意思:第三个是回调函数,总时间是默认值即可)
if (typeof duration === 'function') {
callback = duration;
duration = 1000;
}

//=>准备数据
let time = 0,
begin = {},
change = {};
utils.each(target, (key, value) => {
begin[key] = utils.css(ele, key);
change[key] = value - begin[key];
});

//=>设置新动画之前清除原有正在运行的动画
clearInterval(ele.animateTimer);
ele.animateTimer = setInterval(() => {
time += 17;
//->动画结束
if (time >= duration) {
clearInterval(ele.animateTimer);
utils.css(ele, target);
callback && callback.call(ele);
return;
}
//->获取每个方向的当前位置,并且给元素设置
utils.each(target, (key, value) => {
let cur = effect.Linear(time, begin[key], change[key], duration);
utils.css(ele, key, cur);
});
}, 17);
};
}();
-------------本文结束感谢您的阅读-------------