JavaScript笔记

JS

匿名函数

1
2
3
(function(){})();<!--立即执行函数-->
<!--或-->
(function(){}());

函数

动态参数

1
2
3
4
function fun(){
console.log(arguments) <!--获得动态参数,伪数组,只存在函数-->
}
fun(1,23,5,123)

剩余参数

1
2
3
4
5
6
7
8
9
<!-真数组-->
function fun(...arr){ <!--"arr"是随便取个名字-->
console.log(arr) <!--1,2,3-->
}<!--剩余参数是取剩下的参数-->
fun(1,2,3)
function fun(a,b,...arr){
console.log(arr) <!--"arr"真数组4,3-->
}
fun(1,2,4,3)

展开运算符

1
2
3
4
5
6
const arr=[1,2,4]
console.log(...arr) <!--“...”在数组当中是展开,打印“1 2 4”-->
console.log(math.max(..arr))
console.log(math.min(..arr))
const arr1=[3,5,6]
arr2=[...arr,...arr1] <!--两个数组合并-->

*箭头函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<!--两个"()"表示传参数的地方,"=>"表示function-->
<!--箭头函数没有arguments,只有剩余参数-->
<!--箭头函数没有this,用this会寻找上一层的用这个,最外面是windows-->
const fun=(x)=>{
console.log(x) <!-- "()"多个参数就得用-->
}
fun(1)
const fun=x=>{
console.log(x) <!--如果只有一个参数可以省略"()"-->
}
fun(1)
const fun=x=>x+x <!--如果只有一行代码则默认是“return”,
console.log(fun(1))
const fun=(uname)=>({uname:uname}) <!--要返回对象字面量,则需要加“()”,因为不加"()",直接加“{}”会搞混,到底是执行返回还是执行代码-->
console.log(fun('刘嘉乐'))

数组(Array)

增删改查

1
2
3
4
5
let arr=[];
arr.push('','',...) <!--末尾添加-->
arr.unshift('','',...) <!--开头添加-->
arr.por() <!--删除最后一个-->
arr.shift() <!--删除第一个-->

数组中的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const arr=[5, 12, 8, 130, 44]
arr.join('') <!--将数组连接成一个字符串,输入任意分隔符,空格就为空,512813044-->
arr.find(item=>item>10) <!--只会判断第一次,"12",否则返回undefined-->
arr.every(item=>item<140) <!--只会返回布尔值,所有的都必须小于140,否则返回false-->
arr.some(item=>item==5) <!--只会返回布尔值,只要有一个等于5,否则返回false-->
const arr1=[124,12,1,5]
arr.concat(arr1) <!--[5,12,8,130,44,124,12,1,5],合并两个数组新成新的数组-->
arr.sort() <!--默认排序是将元素转换为字符串,然后按照它们的 UTF-16 码元值升序排序,改原有的数组引用地址-->
arr.toSorted() <!--这个和sort()一样但是返回新数组-->
arr.splice(1,0,'6')<!--[5,6,12,8,130,44],"0"表示不删除只增加,如果给2表示删除2个增加一个6-->
arr.toSpliced() <!--和splice一样但是返回新数组-->
arr.reverse() <!--返回倒序的数组改原有的数组引用地址-->
arr.toReversed() <!--和reverse一样但是返回新数组-->
arr.findIndex(item=>item>13) <!--只会判断一次,并输出该数组的索引,没有则返回"-1"-->
Array.form() <!--将伪数组转换成真数组,生成新数组-->
arr.indexOf(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
let arr=['',....]
<!--遍历数组值-->
for(let i=0;i<arr.length;i++){
console.log(arr[i])
}
<!--这个输出的是数组(数组不常用)-->
for(let i in arr){
console.log(i)
}
<!--遍历数组-->
arr.forEach(function(item,index){
console.log(item) <!--值-->
console.log(index)<!--索引-->
<!--这个“forEach”没有返回值"return"也不会创建新数组,这个适合遍历复杂数组,例套数组对象-->
})
<!-迭代数组-->
<!--map遍历一个数组,并存入一个新数组可增改-->
let arr=['',....]
const trarr=arr.map(function(ele,index){
return`返回新数组,但是代码有换行会多个\n`
})
<!--累计器-->
const arr=[1,2,3,4,5]
const sum=arr.reduce(function (prev,current){ <!--'prev'是上一个值,'current'当前值也可以用"item"
return prev,current
},<!--这里可加'初始值',return返回累计的值最后会加个初始值-->)

过滤

1
2
3
let nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
let res=nums.filter((num)=>num>5); <!--filter创建一个新数组筛选数组中元素并返回到新数组-->
console.log(res); // [6, 7, 8, 9, 10]

对象(obj)

增删改查

1
2
3
4
5
6
7
8
9
10
let obj={
变量名:值,
'变量名中间有特殊符号“-”等' <!--就得在外面输入单引号-->
变量名:值
}
<!--改和增语法一样,判断标准就是对象有没有这个属性,没有就是新增,有就是改-->
console.log(obj.['变量名特殊符号'])<!--查带有特殊符号变量名在外面输入中挂号-->
obj.变量名=值 <!--要成的值-->
obj.新变量名=值 <!--在末尾生成新的-->
delete obj.变量名 <!--要删除的变量名-->

对象中的方法

1
2
3
4
5
6
7
const o={name:'小米',age:'18'}
const arr=Object.keys(o)<!--获得所有的属性名,并返回一个数组-->
console.log(arr) <!--返回所有的属性名,['name','age']-->
console.log(Object.values(o))<!--返回所有的值,返回的是数组-->
const oo={}
Object.assign(oo,o) <!--将o复制到oo完全一模一样的对象-->
Object.assign(o,{time:9}) <!--{name:'小米',age:'18',time:9}

遍历

1
2
3
4
5
6
7
8
let obj={
变量名:值,
....
}
for(let i in obj){
console.log(i) <!--输出的是变量名,但是是字符串-->
console.log(obj[i])<!--输出变量名的值
}

字符串(String)

字符串中的方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const str='你好,JavaScript'
const num=15;
String(num) <!--转换成字符串-->
num.toString() <!--转换成字符串-->
str.length <!--13,获取长度-->
str.split('a') <!--分隔符,将字符串拆分成数组['你好,J', 'v', 'Script']-->
str.substring(1,3) <!--从第1字符的索引开始,获取到3字符的索引(不包括3),'好,',如果没有第二参数,则获取后面所有-->
const str1='Java'
str.startsWith('Java',"可选参数,从哪里位置开始检测") <!--检测是否以某字符开头-->
str.includes(str1,"可选参数,从哪里位置开始检测") <!--判断一个字符是否在另一个字符里有,有就true否就false-->
str.toUpperCase() <!--将字母转换大写-->
str.toLoweCase()<!--将字母转换小写-->
str.indxOf('Java',"可选参数,从哪里位置开始检测") <!--返回一个索引位置-->
str.endsWith('Script',"可选参数,从哪里位置开始检测") <!--检测是否以某字符结尾-->
<!--replace,请看大纲元字符说明-->
str.match('J') <!--用于查找字符串,支持正则表达式-->

数字(number)

数字中的方法

1
2
const sum=12.4124
sum.toFixed(2) <!--保留2位小数,四舍五入-->

内置函数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
console.log(Math.PI) <!--输出的是圆周率-->
console.log(Math.ceil(值)) <!--向上取整-->
console.log(Math.floor(值)) <!--向下取整-->
console.log(Math.round(值)) <!--四舍五入-->
console.log(parseInt(值)) <!--取整,字符串也会转换成整数-->
console.log(Math.max(多个值)) <!--多个值中取最大值-->
console.log(Math.min(多个值)) <!--多个值中取最小值-->
console.log(Math.abs(值)) <!--取绝对值-->
console.log(Math.random()*可乘) <!--随机01小数,可在外套Math.floor取整-->
<!--取n~m随机整数-->
function getRandom(n,m){
return Math.floor(Math.random()*(m-n+1))+n
}
console.log(getRandom(4,8))

DOM

获取元素,内容,节点

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
document.querySelector() <!--获取元素-->
document.querySelectorAll() <!--获取的是数组-->
document.getElementById() <!--获取id-->
document.getElementsByTagName() <!--获取所有标签-->
document.getElementsByClassName() <!--获取所有类-->
innerText <!--获取文本内容也可以替换-->
innerHTML <!--在元素内输出可以文本可以标签-->
<!--节点-->
nodeName <!--名称-->
nodeValue <!--值-->
nodeType <!--类型 1元素 2属性 3文本 8注释 9文档-->
<!--子元素 子节点-->
children <!--获取所有子元素(标签),是伪数组-->
childNodes <!--获取所有子元素和子节点,是伪数组-->
//标签和标签之间的回车也是一个节点
firstChild <!--获取第一个节点-->
lastChild <!--获取最后一个节点-->
firstElementChild <!--获取第一个子元素(标签)-->
lastElementChild <!--获取最后一个子元素(标签)
parentNode <!--获取某元素的父节点——-->
<!--获取相邻节点/元素-->
previousSibling <!--获取相邻上一个节点-->
nextSibling <!--获取相邻下一个节点-->
previousElementSibling <!--获取相邻上一个元素-->
nextElementSibling <!--获取相邻下一个元素-->

创建元素,删除,替换,克隆

1
2
3
4
5
6
7
8
let p=document.createElement('p') <!--创建p标签-->
let text=document.createTextNode("创建文本内容")
p.appendChild(text); <!--将text内容添加到p,也可以是元素-->
p.insertBefore(,) <!--新元素添加到开始位置-->
p.removeChild() <!--移除一个元素,你需要知道该元素的父元素-->
p.replaceChild() <!--替换 HTML DOM 中的元素-->
cloneNode <!--克隆,想克隆子元素需要加“true”-->

元素属性增删改查

1
2
3
<!--都可以增删改查-->
元素.属性名 <!--不能修改自定义属性-->
元素.getAttribute('属性名','值')

添加类

1
2
3
4
classList.add() <!--追加类-->
classList.remove() <!--删除类-->
classList.toggle() <!--切换类-->
className='' <!--直接替换类名-->

data-自定义属性

1
2
3
<div class="box" data-id="10"></div>
box.dataset.id <!--所有一律以data-开头获取里面值都得用dataset对象方式获取-->

定时器

1
2
3
4
5
setInterval(函数,间隔时间) <!--毫秒-->
clearInterval(函数) <!--关闭定时器-->
<!--延迟,但会执行后面代码-->
setTimeout() <!--延迟定时器,只执行一次-->
clearTimeout() <!--清除延迟定时器-->

事件监听和解绑

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
元素对象.addEventListener('事件类型',要执行得函数)
元素对象.removeEventListener('click',function) <!-- 解除事件-->
鼠标事件
click当用户点击某个对象时调用的事件句柄。
contextmenu在用户点击鼠标右键打开上下文菜单时触发
dblclick当用户双击某个对象时调用的事件句柄。
mousedown鼠标按钮被按下。
mouseenter当鼠标指针移动到元素上时触发。
mouseleave当鼠标指针移出元素时触发
mousemove鼠标被移动。
mouseover鼠标移到某元素之上。
mouseout鼠标从某元素移开。
mouseup鼠标按键被松开。
键盘事件
属性描述DOM
keydown某个键盘按键被按下。
keypress某个键盘按键被按下并松开。
keyup某个键盘按键被松开。
框架/对象(Frame/Object)事件
abort图像的加载被中断。()
beforeunload该事件在即将离开页面(刷新或关闭)时触发
error在加载文档或图像时发生错误。(,和)
hashchange该事件在当前URL的锚部分发生修改时触发。
load一张页面或一幅图像完成加载。
pageshow该事件在用户访问页面时触发
pagehide该事件在用户离开当前网页跳转到另外一个页面时触发
resize窗口或框架被重新调整大小。
scroll当文档被滚动时发生的事件。
unload用户退出页面。(和)
表单事件
submit提交表单时触发
blur元素失去焦点时触发
change该事件在表单元素的内容改变时触发(,,,和)
focus元素获取焦点时触发
focusin元素即将获取焦点是触发
focusout元素即将失去焦点是触发
input元素获取用户输入是触发
reset表单重置时触发
search用户向搜索域输入文本时触发(
剪贴板事件
copy该事件在用户拷贝元素内容时触发
cut该事件在用户剪切元素内容时触发
paste该事件在用户粘贴元素内容时触发
打印事件
afterprint该事件在页面已经开始打印,或者打印窗口已经关闭时触发
beforeprint该事件在页面即将开始打印时触发
拖动事件
drag该事件在元素正在拖动时触发
dragend该事件在用户完成元素的拖动时触发
dragenter该事件在拖动的元素进入放置目标时触发
dragleave该事件在拖动元素离开放置目标时触发
dragover该事件在拖动元素在放置目标上时触发
dragstart该事件在用户开始拖动元素时触发
drop该事件在拖动元素放置在目标区域时触发
多媒体(Media)事件
abort事件在视频/音频(audio/video)终止加载时触发。
canplay事件在用户可以开始播放视频/音频(audio/video)时触发。
canplaythrough事件在视频/音频(audio/video)可以正常播放且无需停顿和缓冲时触发。
durationchange事件在视频/音频(audio/video)的时长发生变化时触发。
emptiedTheeventoccurswhenthecurrentplaylistisempty
ended事件在视频/音频(audio/video)播放结束时触发。
error事件在视频/音频(audio/video)数据加载期间发生错误时触发。
loadeddata事件在浏览器加载视频/音频(audio/video)当前帧时触发触发。
loadedmetadata事件在指定视频/音频(audio/video)的元数据加载后触发。
loadstart事件在浏览器开始寻找指定视频/音频(audio/video)触发。
pause事件在视频/音频(audio/video)暂停时触发。
play事件在视频/音频(audio/video)开始播放时触发。
playing事件在视频/音频(audio/video)暂停或者在缓冲后准备重新开始播放时触发。
progress事件在浏览器下载指定的视频/音频(audio/video)时触发。
ratechange事件在视频/音频(audio/video)的播放速度发送改变时触发。
seeked事件在用户重新定位视频/音频(audio/video)的播放位置后触发。
seeking事件在用户开始重新定位视频/音频(audio/video)时触发。
stalled事件在浏览器获取媒体数据,但媒体数据不可用时触发。
suspend事件在浏览器读取媒体数据中止时触发。
timeupdate事件在当前的播放位置发送改变时触发。
volumechange事件在音量发生改变时触发。
waiting事件在视频由于要播放下一帧而需要缓冲时触发。
动画事件
animationend该事件在CSS动画结束播放时触发
animationiteration该事件在CSS动画重复播放时触发
animationstart该事件在CSS动画开始播放时触发
过渡事件
transitionend该事件在CSS完成过渡后触发。
其他事件
message该事件通过或者从对象(WebSocket,WebWorker,EventSource或者子frame或父窗口)接收到消息时触发
online该事件在浏览器开始在线工作时触发。
offline该事件在浏览器开始离线工作时触发。
popstate该事件在窗口的浏览历史(history对象)发生改变时触发。eventoccurswhenthewindow’shistorychanges
show该事件当

阻止冒泡

1
2
事件对象.stopPropagation() <!--是阻止目标元素的冒泡事件,但是会不阻止默认行为-->
事件对象.preventDefault() <!--取消一个目标元素的默认行为。既然是说默认行为-->

offset,client,scroll,page,getBoundingClientRect

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!--元素偏移量offset-->
element.offsetParent <!--返回该元素带有定位的父级元素,如果父级元素没有定位则返回body-->
element.offsetTop <!--返回该元素上外边框相对带有定位的父级元素上内边框的偏移,如果父级元素没有定位则返回相对body上方的偏移-->
element.offsetLeft <!--返回该元素左外边框相对带有定位的父级元素左内边框的偏移,如果父级元素没有定位则返回相对body左侧的偏移-->
element.offsetWidth <!--返回该元素包括padding+border+content的高度-->
element.offsetHeight <!--返回该元素包括padding+border+content的高度-->
<!--元素可视区client-->
element.clientTop <!--返回该元素上边框大小-->
element.clientLeft <!--返回该元素左边框大小-->
element.clientWidth <!--返回该元素包括padding+content的宽度,不含边框-->
element.clientHeight <!--返回该元素包括padding+content的高度,不含边框-->
<!--元素滚动scroll-->
element.scrollTop <!--返回被卷去的上侧距离,从内容顶部到上内边框-->
element.scrollLeft <!--返回被卷去的左侧距离-->
element.scrollWidth <!--返回该元素自身实际的宽度,不含边框-->
element.scrollHeight <!--返回该元素自身实际的高度,不含边框-->
pageX <!--返回该鼠标与整个页面(不包括上面标签)的x坐标-->
pageY <!--返回该鼠标与整个页面(不包括上面标签)的Y坐标
getBoundingClientRect() <!--返回该元素大小及其对于视口的位置

image-20231214155829227.webp

时间

Date()

1
2
3
4
5
6
7
8
let time=new Date();
console.log(date.getFullYear()); //当前日期的年
console.log(date.getMonth() + 1); //月份+1 由于月份是0-11计算 所以需要 +1
console.log(date.getDate()); // 日
console.log(date.getDay()); // 星期几 注意:星期日返回的是0
console.log(date.getHours()); // 时
console.log(date.getMinutes()); // 分
console.log(date.getSeconds()); // 秒

toLocaleString

1
2
3
4
5
let timer = new Date() <!--该方法可以格式化日期和时间,同时衍生出另外两种分别获得日期和时间的方法-->
console.log(timer.toLocaleString()) // 日期+时间 2023/5/28 23:07:35
console.log(timer.toLocaleString('en-US', { timeZone: 'America/New_York' }))
console.log(timer.toLocaleDateString()) // 日期 2023/5/28
console.log(timer.toLocaleTimeString()) // 时间 23:10:31 。

倒计时时间戳

1
2
3
4
5
6
7
8
9
10
function countDown(time) {
let dateNow = +new Date(); // 获取当前时间的毫秒数
let dateOver = +new Date(time); // 获取目标时间的毫秒数
let gapTime = (dateOver - dateNow) / 1000 // 由毫秒得到秒
let s = pad(parseInt(gapTime % 60)); // 秒数
let m = pad(parseInt(gapTime / 60 % 60)); // 分钟数
let h = pad(parseInt(gapTime / 60 / 60 % 24)); // 小时数
let d = pad(parseInt(cha / 60 / 60 / 24)); // 天数
return d + '天' + h + '小时' + m + '分钟' + s + '秒';
}

location(url)

1
2
3
4
location.href <!--获取url的地址-->
location.search <!--获取url带"?"后面的参数-->
location.hash <!--获取url带"#"后面的参数-->
location.reload("传true,就是强制刷新") <!--刷新页面-->
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
console.log(navigator) <!--获取浏览器相关属性-->
navigator.userAgent <!--检测浏览器的版本和平台-->
<!--判断是否为移动端正则表达式-->
!(function () {
const userAgent = navigator.userAgent
// 验证是否为Android或iPhone
const android = userAgent.match(/(Android);?[\s\/]+([\d.]+)?/)
const iphone = userAgent.match(/(iPhone\sOS)\s([\d_]+)/)
// 如果是Android或iPhone,则跳转至移动站点
if (android || iphone) {
location.href = 'http://m.itcast.cn'
}
})();
// !(function () { })();
!function () { }()

history页面(前进,后退)

1
2
3
history.back() <!--后退一个链接页面-->
history.forward() <!--前进一个链接页面-->
history.go() <!--1是前进一个,-1是后退一个......-->

本地存储

localStorage,sessionStorage(字符串数据库)

1
2
3
4
5
6
localStorage <!--关掉浏览器还是有数据,存在电脑上,必须用户手动删除-->
<!--key得带单引号-->
localStorage.setItem(key,value) <!--变量名,值,没有这个变量名就是增,有就是改值-->
localStorage.getItem(key) <!--读取数据库值-->
localStorage.removeItem(key) <!--在数据库删除该变量和值-->
sessionStorage <!--关掉浏览器直接清空数据,用法和localStorage一样-->

将复杂类型互转换JSON

1
2
JSON.stringify(复杂类型) <!--例对象,但是获取的是字符串-->
JSON.parse(JSON字符串) <!--转换为对象-->

正则表达式

1
2
3
4
5
<!--正则都是以“//”在中间写规则-->
reg=/定义规则/
<!--也可以直接写,定义规则.test()或exec()-->
reg.test('要判断是否为reg写的符合规则') <!--返回true,false-->
reg.exec('要判断是否为reg写的符合规则') <!--返回一个数组,检索查找,没有为null-->

元字符

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
<!--边界符-->
<!--里面加"|"表示或-->
<!--"^"开头是什么,“$”结尾是什么"g"/外面加g表示全局匹配-->
/^哈/ <!--开头为哈都为true-->
/^哈$/ <!--精确匹配,前后都为"哈",一个字符-->
<!--量词-->
/^哈*$/ <!--"*"表示“哈”后面可以以>=0次出现,为空也是true,但两个字符以上,第一个字必须为“哈”和结尾为"哈",而且中间不能有以"哈"以外字,否则为false-->
/^哈+$/ <!--"+"表示>=1,必须有一个,和"*"差不多-->
/^哈>$/ <!--0||10个哈或者1个哈-->
/^哈{n}$/ <!--例n输入4,哈必须为4个-->
/^哈{n,}$/ <!--例n输入4,哈必须4以上-->
/^哈{n,m}$/<!--例n输入4,m为8,哈必须在4-8之间-->
<!--“[]”可匹配里面所有的字符-->
/[abc]/ <!--a或b或c-->
/^[abc]$/ <!--“^&为精确匹配”a或b或c,但只能一个-->
/^[abc]{n}$/ <!--例n为2,必须为2个字符,前后都属于abc当中-->
<!--“-”为范围-->
/^[a-zA-Z0-9]$/ <!--a到z或大写或09,必须为一个,范围也得是里面-->
/^[a-zA-Z0-9]{n}$/ <!--a到z或大写或09,必须为"n"个,范围也得是里面-->
<!--在"[]"中间加"^"表示取反-->
/^[^a-zA-Z0-9]$/ <!--a到z或大写或09以外的,必须为一个-->
<!--"."表示匹配除换行符之外的任何单个字符-->
<!--"//"后面加i表示不区分大小写,g是匹配所有满足正则表达式的结果,ig都可以加-->
/^$/i.test()
<!--replace,用正则表达式替换-->
const tr='java是一门非常好的,JAva工资高'
re=tr.replace(/Java/gi,'前端') <!--只加i只替换一个-->
console.log(re) //前端是一门非常好的,前端工资高

2023-12-16_16-42-21.webp

构造函数

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
<!--构造函数首字母大写,只能用new,没有return,this指向实例对象-->
<!--每个对象构造函数最上层有Object,再上面就是null-->
function Obj(name,age,gener){
this.name=name;
this.age=age;
this.gener=gener;
}
<!--创建实例对象-->
const item1=new obj("乔治",18,"女")
const item2=new obj("猪妈妈",59,"女")
console.log(item1) <!--{name:'乔治',age:18,gener:'女'}

<!--原型对象,有一个prototype,指向constructor里面有构造函数数-->
Obj.prototype <!--prototype是一个对象,但里面有constructor这个里面就是Obj构造函数-->
Obj.prototype.s=function (){ <!--这个就相当于吧函数添加到prototyoe对象里,此时这里面有s和构造函数Obj,这样所有实例要调用这个函数,只会在内存当中出现一次-->
console.log('共享一个方法')
}
item1.s() <!--调用-->
Obj.prototype.constructor <!--constructor指的是这个构造函数Obj,爹-->
<!--对象原型,这个是实例化对象指向constructor里面有构造函数-->
s1.__proto__ <!--指向prototype,"注意__proto__和[[Prototype]]是一样意思"-->
<!--上方就是一家三口-->
<!--原型链,每个构造函数的prototype都有Object构造函数-->
Obj.prototype.__proto__ <!--指Object.prototype-->
<!--原型链-->
<!--instanceof判断是不是在object原型链-->
console.log(item1 instanceof Obj) <!--判断item1实例是不是Obj构造函数创造的,返回truefalse-->
console.log(item1 instanceof Object) <!--true-->
console.log(item1 instanceof Array) <!--false-->
console.log([1,2,3] instanceof Array) <!--true-->
console.log(Array instanceof Object) <!--true 万物皆对象-->

递归函数

其本质意思就是可以调用自己,但是得有退出,否则会溢出

1
2
3
4
5
6
7
8
9
let i=1
function s(){
if(i>6){
return
}
i++;
s()
}
s();

深浅拷贝

浅拷贝和深拷贝只针对引用类型

浅拷贝

浅拷贝复制的是地址

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const Obj={
name:'LvemiX',
age:18,
functions:{
text:'520',
}
}
// 第一种复制
const copy={...Obj};
// 第二种复制
const copy={ };
Object.assign(copy,Obj);
copy.functions.text='250';
// 数组浅拷贝
const arr=["LvemiX",18,["520"]]
// 第一种复制
const copy=[...arr]
// 第二种复制
const copy=Array.prototype.concat(arr)
arr[2][0]="250";
console.log(arr);
console.log(copy);

// 如果里面多层复杂,浅拷贝只会复制地址,并不会复制值

深拷贝

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
const Obj={
name:"LvemiX",
age:20,
text:["520",{numbers:70}]
};
// 下方是判断数据类型,来继承用户给的类型
function Type(type){
if(type instanceof Array){
return []
}else if (type instanceof Object) {
return {}
}
};
// 深拷贝,无论怎么改都是不会改旧数据
function DeepCopy(newCopy,oldCopy){ // 递归函数
for(let i in oldCopy){
if(oldCopy[i] instanceof Array){ // 先判断数组,因为console.log([] instanceof Object) 也是对象
newCopy[i]=[]
DeepCopy(newCopy[i],oldCopy[i])
}else if (oldCopy[i] instanceof Object) { // 对象不是数组类型
newCopy[i]={}
DeepCopy(newCopy[i],oldCopy[i])
}else{
newCopy[i]=oldCopy[i];
}
}
return newCopy // 返回新数据
};
const copy=DeepCopy(Type(Obj),Obj);
Obj.text[1].numbers=80;
console.log(Obj);
console.log(copy);

Lodash API

_.clone

创建一个value的浅拷贝

1
2
3
4
var objects = [{ 'a': 1 }, { 'b': 2 }];
var shallow = _.clone(objects);
console.log(shallow[0] === objects[0]);
// => true

_.cloneDeep

这个方法类似_.clone,除了它会递归拷贝 value。(注:也叫深拷贝)。

1
2
3
4
var objects = [{ 'a': 1 }, { 'b': 2 }];
var deep = _.cloneDeep(objects);
console.log(deep[0] === objects[0]);
// => false

更多内容请参考Lodash 简介 | Lodash中文文档 | Lodash中文网 (lodashjs.com)

用JSON深拷贝

1
const o=JSON.parse(JSON.stringify(obj)) // 先吧对象转换JSON,再吧JSON转换对象,这样复制的不会和原来相关

异常处理

throw抛异常

1
2
3
4
5
6
7
8
9
function error(x,f){
if(!x||!f){
throw new Error('参数不能为空')
// 程序会终止运行
// Error对象配合throw使用,能够设置更详细的错误信息
}
return x+f
}
error()

try-catch-finally

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function error(){
try{
// 可能会错误的代码,可以写道try,由catch发送控制台错误
const p = document.queryselector('.p');
p.style.color='red';
}catch(err){
// 拦截错误,提示浏览器提供的信息错误,但是不中断后面的程序
console.log(err.message)
// 需要return中断程序
return
// 也可以用throw中断并抛出异常
throw new Error('报错了')
}finally{// 必须执行的一段,不管报没报错
alert('执行了,后面不会执行了')
}
console.log(1)
}
error()

debugger

1
2
3
4
5
6
7
const a=[1,2,3,4];
for(let i=0;i<a.length;i++){
debugger // 断点,在浏览器控制台可一步一步执行该代码,查看实时变量
a[0]+=5;
console.log(a[0])
}
console.log(a)

this改变指向

call

1
2
3
4
5
6
7
8
const obj={
uname:'LvemiX'
}
function a(x,y){
console.log(this)
console.log(x+y) // 3
}
a.call(obj,1,2,……) // 这时this指向着是obj,则后面可以传参到函数里,会调用函数

apply

1
2
3
4
5
6
7
8
9
10
11
12
const obj={
uname:'LvemiX'
}
function a(x,y){
console.log(this)
console.log(x+y) // 3
}
a.apply(obj,[1,2,……]) // 这个和call一样,但是传参必是用数组来传参,会调用函数

const arr=[1,2,3]
const max=Math.max.apply(null,[1,2,3]) //Math.max也是函数可以用apply,this可以为null
const max=Math.max.apply(null,arr)

bind

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const obj={
uname:'LvemiX'
}
function a(x,y){
console.log(this)
console.log(x+y) // 3
}
const b=a.bind(obj,1,2,……) // bind会将原函数拷贝成新函数,新函数this会改变,原函数不会,不会调用函数
b()

document.querySelector('button').addEventListener('click',function (){
this.disabled=true;
setTimeout(function(){
this.disabled=false // 这时this指向着window,window.setTimeout
}.bind(this),2000) // 这里this指着是button,顺便将setTimeout中的this替换成setTimeout外面的this,也就是button
})

Set对象

Set 对象允许你存储任何类型的唯一值,无论是原始值或者是对象引用

Set 对象存储的值总是唯一的,所以需要判断两个值是否恒等。有几个特殊值需要特殊对待:

  • +0 与 -0 在存储判断唯一性的时候是恒等的,所以不重复;
  • undefined 与 undefined 是恒等的,所以不重复;
  • NaN 与 NaN 是不恒等的,但是在 Set 中只能存一个,不重复。
1
2
3
4
5
6
7
8
9
10
11
12
let mySet = new Set();

mySet.add(1); // Set(1) {1}
mySet.add(5); // Set(2) {1, 5}
mySet.add(5); // Set(2) {1, 5} 这里体现了值的唯一性
mySet.add("some text");
// Set(3) {1, 5, "some text"} 这里体现了类型的多样性
var o = {a: 1, b: 2};
mySet.add(o);
mySet.add({a: 1, b: 2});
// Set(5) {1, 5, "some text", {…}, {…}}
// 这里体现了对象之间引用不同不恒等,即使值相同,Set 也能存储

类型转换

Array

1
2
3
4
5
6
7
8
// Array 转 Set
let mySet = new Set(["value1", "value2", "value3"]);
// 用...操作符,将 Set 转 Array
let myArray = [...mySet];
String
// String 转 Set
let mySet = new Set('hello'); // Set(4) {"h", "e", "l", "o"}
// 注:Set 中 toString 方法是不能将 Set 转换成 String

Set 对象作用

数组去重

1
2
let mySet = new Set([1, 2, 3, 4, 4]);
[...mySet]; // [1, 2, 3, 4]

并集

1
2
3
let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);
let union = new Set([...a, ...b]); // {1, 2, 3, 4}

交集

1
2
3
let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);
let intersect = new Set([...a].filter(x => b.has(x))); // {2, 3}

差集

1
2
3
let a = new Set([1, 2, 3]);
let b = new Set([4, 3, 2]);
let difference = new Set([...a].filter(x => !b.has(x))); // {1}

防抖

单位时间内,频繁触发事件,只执行最后一次

  • 防抖是指在一段连续操作结束后,等待一定时间,如果在这段时间内没有再次触发该操作,则执行该操作。
  • 典型应用包括输入框输入事件,只有在用户输入完成后的一段时间内才执行搜索请求,避免频繁请求接口。
  • 适合处理一些“只需最后一次”的情况。

_.debounce

1
2
3
4
5
6
7
8
9
10
11
12
13
let i=0;
const div=document.querySelector('div')
// 创建一个需要进行防抖处理的函数
function add(){
// 在这里放置需要进行防抖处理的代码
div.innerHTML=i++;
}
// 使用_.debounce创建防抖实例
// 第二个参数是等待时间(以毫秒为单位)
div.addEventListener('mousemove',_.debounce(add,300))
// 现在,当鼠标移入div时触发add函数,它将在最后一次调用后的300毫秒内不再执行add函数。
// 例如:
// 在300毫秒内再次触发div将不会立即触发add函数,而是重新计时。

手写防抖

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
let i=0;
const div=document.querySelector('div')
// 创建一个需要进行防抖处理的函数
function add(){
// 在这里放置需要进行防抖处理的代码
div.innerHTML=i++;
}
// 防抖函数
function debounce(fn,t){
let timer
return function(){
if(timer)clearTimeout(timer)
timer = setTimeout(function(){
fn()
},t)
}
}
div.addEventListener('mousemove',debounce(add,300))

节流

单位时间内,频繁触发事件,只执行一次

  • 节流是指在一定时间间隔内只执行一次操作。
  • 比如页面滚动事件,我们可能每隔一定时间处理一次滚动事件,而不是每次滚动都去执行操作。
  • 适合限制操作的执行频率,特别是在高频触发的场景下。

_.throttle

1
2
3
4
5
6
7
8
9
10
11
12
13
let i=0;
const div=document.querySelector('div')
// 创建一个需要进行节流处理的函数
function add(){
// 在这里放置需要进行节流处理的代码
div.innerHTML=i++;
}
// 使用_.throttle创建节流实例
// 第二个参数是等待时间(以毫秒为单位)
div.addEventListener('mousemove',_.throttle(add,300))
// 现在,当鼠标移入div时触发add函数,它将在执行一次,调用后的300毫秒内再次触发则取消。
// 例如:
// 在300毫秒内再次触发div将取消立即触发add函数。

手写节流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
let i=0;
const div=document.querySelector('div')
// 创建一个需要进行节流处理的函数
function add(){
// 在这里放置需要进行节流处理的代码
div.innerHTML=i++;
}
// 节流函数
function throttle(fn,t){
let timer =null;
return function(){
if(!null){
timer = setTimeout(function(){
fn();
timer=null; // 再运行setTimeout中不允许在里面用clearTimeout清楚定时器,直接赋值空下次判断就没有
},t)
}
}
}
div.addEventListener('mousemove',_.throttle(add,300))

AJAX

基础配置

1
2
3
4
5
6
7
const xhr=new XMLHttpRequest;
xhr.open('方法','url');
xhr.addEventListener('loadend',()=>{
console.log(xhr.response);// 返回的市JSON字符型
const data=JSON.parse(xhr.response)// 转换为js中的对象
})
xhr.send()

查询

1
2
3
4
5
6
const xhr=new XMLHttpRequest;
xhr.open('方法','http://xxxx.com/api/city?参数名1=值&参数名2=值...');// 要查询的话,参数要自己拼接,两个以上的参数要加'&'拼接符
xhr.addEventListener('loadend',()=>{
console.log(xhr.response);
})
xhr.send()

URLSearchParams

1
2
3
4
5
const paramsObj=new URLSearchParams({
参数名1:值1,
参数名2:值2
})
const queryString=paramsObj.toString() //转成字符串型

发送

1
2
3
4
5
6
7
8
9
10
11
12
const xhr=new XMLHttpRequest();
xhr.open('post','url');
xhr.addEventListener('loadend',()=>{
console.log(xhr.response);
})
xhr.setRequestHeader('Content-Type','application/json') // 设置请求头,类型 JSON
const userObj={
username:'LvemiX',
password:'123456'
}
const json=JSON.stringify(userObj) //将js对象转换JSON字符
xhr.send(json) //发送并传JSON数据

Promise

用于表示一个异步操作的最终完成(或失败)及其结果值。

1
2
3
4
5
6
7
8
9
10
11
const p =new Promise((resolve,reject)=>{
// 执行异步任务,并传递结果
// 成功调用:resolve触发then
//失败调用:reject触发catch
})
p.then(result=>{
// 成功
console.log(result)
}).catch(error=>{
// 失败
})