JS基础-D1
变量类型
1.js编程语言,html标记语言
2.不用jdk,运行在浏览器
3.交互,用户点击+1就数值+1
4.服务端编程,nodejs
5.js遵循ecma-script的语法规范
6.js由ecma-s和dom bom组成,或者也可以叫做ecma-s和webapi组成
(Document object model 和 Browser object Model)
评论,点击,操作dom对象, 确定是否删除的提示框操作bom对象
7.顺序加载,尽量写在前,防止dom未加载 js处理逻辑时找不到对象
8.输出dom.write(“
xxx”)
9.alert跳过渲染先执行 prompt输入框弹出
变量
1.盒子,装数据的 let xxx=214
2.不能声明多个变量
3.多个变量逗号隔开
4.伪代码,中文想法先写后续翻译代码
5.变量交换,冒泡排序里的那个temp
6.从内存申请来的空间(在一栋楼里租了一间房有地址北京市xx区404),持续崩溃后消失
常量
1.必须初始化,不能修改,const xxx=123
数据类型
1.分为基础,和引用,
- 基础为number数字/string字符/boolean布尔/undefined未定义/null空
数字类型
负数小数,浮点数整数 long全为数字类型number。还有一个为NaN,计算错误显示这个,例如你用字符串减数字
字符串
1.单引号,双引号,反引号包裹,推荐单
2.字符串拼接数字,同化数字为字符串
undefined
1.没有初始值则位undefined
2.和null的区别,null表示赋值了,undefined表示未赋值,一般null可以用来给对象初始化,typeOf能读到是object 而不是undefined
3.typeof(变量名)可以获取变量的类型
类型转换
为什么
prompt读的的字符串,计算操作100+200 为100200,先转number再计算
隐式转换
除+号,其他计算会将数据转为数字类型,不过+号放前面可以转换为数字类型
数字字符串+数字隐式转换 结果为字符串
显示转换
Number(变量名)
parseInt/float()转整或浮点数 如果字符串里有px。啥的字符串,最后提纯为数字
最好数字打头,否则NaN计算错误
运算符
一元, a+=1,二元 a=1+1 三元 1+1==3?
自增
前后自增区别 前相当于打了个小括号, 后相当于战斗结束喝杯水
前自增在运算前。后在运算后,如果单纯i++。没有运算,也算运算结束,下一个+ ++i为运算后的值
2.+=简化运算 num=num+1 为num+=1
比较运算符
2=='2’隐式转换数字类型, 为true
2===‘2’ 没转换,且判断类型,和值全等才可以
NaN===NaN false, nan不等于任何人包括自己
字母比较,比ASCII码,a=a 比下一个字符
表达式和语句
表达式为式子,有结果
语句为一段代码,语句不一定有返回值 可能为void
定时器案例
小于10,直接前加0,虽接收字符串但 隐式转换
断点调试
和java的编译不一样,直接浏览器运行即可
鼠标移上去得到目前值,更好的说明了js运行在浏览器
逻辑判断
if和switch
switch更效率,case用链表维护,更快定位,而if从上到下,不过更灵活(case匹配采用全等于)
少分支,if 多分支switch
数组
修改
arr[索引]=修改值
push数据加在后面,unshift加在前面
pop取出最后一个值
shift取出第一个值
splice (起始位置,删除个数)第二个数不指定则后面一段全删
splice (起始位置,0《表示不删除》,替换或新增的元素)
案例-去0
一个新数组,一个老数组fori循环判断值
函数
具名函数
命名
- 动词前缀
- 小驼峰
声明
function 函数名字(参数1,2){}
java还需指定类型
参数1,2为形参,外部调用他为实参
参数可以给默认值,参数1=默认值1 类似初始化,使其结果不为NaN
如果是数组调用记得给初始化空数组,否则undefined是没有length属性的
bug
函数里面写num=10.但是没有在外部声明, 外部居然能拿到这个num
函数内部声明的变量和外部声明的优先就近原则(java里好像不能再方法里定义变量)
函数也一样就近原则
匿名函数
没有名字?怎么调用?
1.函数表达式,定义匿名函数赋值给一个变量,调用变量()
2.具名可以任意书写调用位置 ,匿名函数必须先声明函数表达式再调用
3.立即执行函数
在函数内部声明的变量
声明
先写俩小括号
()()
前面补充匿名函数
(function(){})() 为什么不直接写 function(){}() 因为函数没声明名字也没用变量接收会报错
写完后面必须加分号
也可以加载前面卧槽花里胡哨的,装大b
总体为两部分,前面小括号定义匿名函数,后面小括号调用,你也可以把后面的小括号提到前面的匿名函数声明后面
作用
防止变量污染,将每个num变量用一个小盒子给他隔开,自调用,无需手动调用
立即执行函数内部不一定是匿名的,也可以是有名字的
实际用处
第三方js文件内部定义的变量只在该js里的方法内生效,不影响用户外部定义的变量
4.函数内部的变量用let定义,不用let的话其作用域会跑到外面
逻辑中断
1.后续从localstorage里获取到的 localstorage.getItem(xxx) || []就用到了这个,如果你想要拿一个不确定是否存在的值可以使用,就是后备隐藏能源,备选方案,当第一个爆了之后获取后面的,如果第一个没爆就是存在就拿抵押给
类似函数形参的默认值
2,与之相似的有&& 如果第一个值爆了,直接摆烂,没有备选方案了
转换为Boolean值
显示
undefined ,null NaN,‘’,undefined为假。用来if判断
隐式
1.数值加空串,转为字符串类型的数字
2.空串 减法。 转为数字类型 计算结果 ‘’-1 =-1 —— ‘1’-1=0
字符串的数字加转字符串,减转数字类型
字符串汉字与数字类型做计算为NaN
3.null 转0, null+1=1
4.undefined做计算为NAN
null==undefined为真
null===undefined为假
对象
无序数据的集合
增删改查
删
delete obj.name
增
obj.新属性名=值
改
obj.name=1
查
obj.xxx
obj[‘ddd-xxx’]用了短横线就得使用这种,否则解析为减号计算了
对象内的函数
对象属性值的遍历
1.不能用for循环,没下标
2.使用for (属性 in 对象) 然后拿着这个属性obj.属性拿属性值
等等,for 取出来的属性为字符串的,那就不能用obj.属性了,得用这个了obj[属性]
内置对象
1.js自带
2.数学对象Math 随机方法random()
math
-
ceil 1.1/1.6 天花板直接到2
-
round 四舍五入, -20.5可不是 -21,而是-20
-
floor 小数点后的取除,不过只能针对数字类型,parseInt还能针对’12px‘字符串
-
random
由于最大只能到0.999 因此想要*10得到10,必须乘11然后拿到一个10.999的floor去小数
抽奖,索引下标随机,然后取值, 这里索引下标范围可以直接为length因为左闭右开,最大范围那个原始要+1,可索引下标从0开始-1刚好抵消掉
0-N的随机数 random * (N+1)
n-M的随机数 random (M-N+1)+N 这个是为了获取0到x的随机数,然后再补回去减去的值N 举个例子, 5-10 , 我们是不是可以先求0-5, 然后后面再+5呢,如果求得是0,+了5不就是5, 是3,加了5就是8 了
WEB~API-D1
变量const优先
1.变量声明const优先,简单数据类型声明后变量不做改变
2.数组和对象可以使用const。然后后续改变。因为存在堆里面,改的是真实值,其变量地址没有改变不过你如果想要const arr=[1,2,3] 然后改成arr=xxx。就报错
dom树和dom对象
1.dom document object model 文档对象模型。操作网页内容的对象
dom根-head-body-n个div
2.dom对象是根据html标签生成的js对象。好比将死的页面交给一个人管理,我们可以和这个人沟通从而改变html标签,使其页面发生变化
3.遍历querySelectorAll拿到的数组是伪数组,没有pop push方法
4.获取参数填写css选择器
5.innerText不解析html,innerHtml解析html。document.innerHTML(‘标签…’)
6.随机图片,随机数+模板字符串,不需要将多张img引用写数组,只需动态的改变地址路径
修改样式
对象.style.属性(多组单词用驼峰)=值
操作类名
1.优点,不用调用多个style属性赋值
2.classList /add/remove/toggle 操作 toggle类似于className覆盖
3.轮播图下面的小圆点可以通过 qs随机random然后nth-child(n)=active高亮。不用qsa(queryselectAll)因为这里把一个选出来加工就行。qsa还得根据random去加样式
获取表单值
对象.value / checked / type 给checked设置字符串值,除了空字符串,都为true
自定义属性
使用data-属性名定义
用:对象.dataset.属性名获取
定时器
一个间歇,几秒执行一次,一个倒计时,倒计时结束后执行
setInterval/TimeOut (匿名/箭头函数《如果具名函数就不加小括号》,时间)
清除定时器先给定时器一个变量存储,然后通过变量来调用定时器上的方法.clearInterval
案例
倒计时,disabled改为false,内容改为同意
轮播图
可以直接开头对i取余8,这样就能获得0-7的下标,结尾的时候自增,如果自增到8下一次循环开始8%8为0,又从头开始,减少一次判断
事件监听
触发源头,类型(点击还是经过),事件函数
案例
随机点名
监听,定时器,点击开始按钮不断的根据随机数innerHTML, 点击结束按钮清除定时器,并且根据随机数删除当前的元素,也就是随机到一个数取出来,
事件
监听版本
onclick和add…(click,function) 第一种声明多次会覆盖,第二种会执行两次点击事件的函数调用
事件类型
轮播图案例
更换小圆点,
获取classList,然后移除active属性,然后再根据index给li:nth-child(n)加active
一般来说0-7为每个数据索引到8说明结尾了,大于8防止用户同时点了两下按钮变为9
自动调用点击事件
自动轮播也就是 无数个下一页的操作放在了定时器,在定时器里对按钮点击next.click()即可,当鼠标进入时,定时器清除,切换为手动挡,鼠标移出时,继续定时,赋值粘贴创建定时器给变量的代码(不用变量接收管理定时器找不到,关不了掉黑洞里去了)
next不是dom标签吗,因为addEven click监听自动给其设置了函数
字数统计案例
文本域.value.length
事件对象
1.监听时间的函数设置形参e 或者event接收事件触发的对象
type类型,clientX/clientY,触发事件相当于可视窗口的x,y坐标
offsetX/offsetY 当前光标相当于dom的起点xy位置
老版keycode,新版key
评论回车发布案例
1.按回车不触发,回车松开触发,否则长按一直触发不好
2.trim去空格不为空才innerHTML否则 清空输入框用户重输
- if(xxx.trim()) / if (xxx.trim()!==‘’)
环境对象
1.谁调用this就是谁
回调函数
1.函数作为形参给另一个函数的内部进行调用, 调用A函数,A函数在调用B函数
综合案例TAB栏切换
<script>
//1.获取所有tab,为其绑定监听事件
const tabs = document.querySelectorAll('.tab-item')
for (let i = 0; i < tabs.length; i++) {
tabs[i].addEventListener('mouseenter', function () {
//排他思想,先找到皇上,干掉,自己登基
document.querySelector('.tab .active').classList.remove('active')
//登基
this.classList.add('active')
// 内容登基
document.querySelector('.products .active').classList.remove('active')
document.querySelector(`.products .main:nth-child(${i + 1})`).classList.add('active')
})
}
</script>
排他思想,先找到亮的那个哥们,给他干掉,然后将当前监听的哥们加active给table栏和内容区域, active(block,或橙色高亮)
全选框案例
根据全选框的check值给所有的子check赋值
以上是大头控制小头,接下来小头控制大头, 利用css伪类选择器特性,当勾选时,复选框有一个 xx:checked 选择器属性
给每一个复选框监听,每勾选一个,检查当前有:checked的属性的个数是否为总长度,是的话全选box勾选
不用if判断了,如果相等就是一个布尔值了,而box所需的结果就是一个布尔值,省写了代码
事件流
1.两种,一种叫捕获,外部流向内部,一种叫冒泡,内部流向外部
捕获
第三个参数开启true,开启后父元素的事件全部触发
分别监听三代,点击孙子,父爷辈分的都触发了
冒泡
1.所有父级元素的同名事件触发,在第三个参数加false,默认是false不写就是冒泡
阻止冒泡
不想连带效应,子牵扯父
stopPropagation
移除事件
老版直接null置空
新版使用remove方法,指定函数名和事件名,
二者区别
on
- null覆盖实现解绑
- 后注册覆盖前注册
- 冒泡阶段执行
addEventListenter
- 后注册不覆盖前,同一个事件多个函数调用
- 第三个参数true 捕获, 不写或者false为冒泡
- removeEven…移除 ,匿名解绑不了
mouseover和mouseout默认冒泡当父元素有监听,子元素没有,不过你鼠标经过子元素同样会触发父元素的冒泡,因为子元素在父元素的范围内,强行让子元素冒泡执行,后续做事件委托
mouseleave和enter没有冒泡
事件委托
使用场景,ul里的多个li不需要每个都设置监听器了,给ul设置监听器然后子元素冒泡传递事件对象即可,强行监视所有子元素的事件行为,类似把孩子放到一个屋子,只要有一个孩子哭了就会触发父元素的报警事件
当子元素冒泡上去后父元素监听事件使用e.target接收事件对象
2.事件委托的this为父元素,子元素为e.target 该对象上还有一个tagName属性,区分不同类型的子元素
3.tab栏切换给父元素监听点击事件,子元素触发拿到e之后对e身上的自定义属性定位到对应的li设置样式和修改 tab content内容为block
阻止默认行为
阻止提交和跳转的默认行为 e.preventDefault
其他事件
1.页面加载事件
所有dom和资源加载完毕后的事件
等到所有div或者img图片加载完毕后执行的函数
2.所有标签加载完毕后的事件,不等图片样式表加载后的事件
刚才是给window监听,现在是document监听,这个更快一点
3.元素滚动事件
滚动的位置
scrollTop大小就是元素被滚动条卷去也就是隐藏的高度
滚动条下滚,页面头部相当于当前视窗上走的距离,被滚动隐藏的距离
类似于卷轴,头顶往内卷的长度
4.获取页面滚动距离
- 获取html被卷去的距离(最大的) document.documentElement.scrollTop
- 数字类型,不是88px这种的,可改的
一种修改属性,一直调方法
5.尺寸变化事件
标签可见元素宽度获取,不包含border
6.盒子的宽度offsetWidth/height(包含内容+padding+border的大小) 在html距离顶部的位置offsetTop 距离左边则是offsetLeft,前提是父盒子没有定位,有定位则针对父盒子的左/上边线距离,没定位以文档左上角
b站切换tab底部红条跟随案例
计算li 的offsetLeft然后点击后translateX为left值即可
获取位置
1.e.getBoundingClientRect在可视区范围内,受滚动条的影响
2.offsetTop 不受滚动条,相当于html文档
3.scrollTop,头部被吃掉的距离,可读写
4.clientWidth不包含 border和margin的元素宽度,只读
5.offsetWidth 包含border padding 滚动条的元素宽度,只读
点击后页面跳转且高亮案例
1.事件委托 点击事件
2.判断为a标签且 必须有自定义属性才能进行跳转或者高亮移除或增加(排除跳转顶部的那个按钮的高亮参与)
3.拿dataset和 要跳转的div上的class属性比对拿到offsetTop距顶值,然后这个距顶值覆盖scrollTop则滚到上面
4.页面滚动滑动丝滑效果使用样式
html{
scroll-behavior:smooth;
}
4.监听滚动事件,滚动
时间对象
1.new 一个实例, 可以参数指定时间,如果是+new Date()则获得时间戳
2.实时时间案例
获取时间戳
倒计时案例
拿到现在的时间戳和指定时间的时间戳,相减/1000拿到秒,根据公式获得时分秒,时的算出来有几天然后%24,剩下不足一天的余数作为小时,然后判断是否大于10进行补0操作
封装函数并初始化调用
DOM节点
元素(div),属性(class),文本(span p h1)
查找节点
1.元素.parentNode获取父节点。点击X按钮 关闭父节点的广告区域。且相同类名的父盒子不用担心class冲突,只关注于自己的父节点。用循环先每个设置下监听
2.元素.children子节点 x.previousElementSibling 上一个兄弟节点,nextElementSibling下一个
增加节点
1.末尾/前面增加,可以先写一个样式,后续循环插入li
2.克隆节点
true为深克隆,不加为浅克隆,区别就是多了标签的内容
删除节点
父元素.removeChild 经过父亲同意
移动端事件
触摸,移开,滚动
轮播图插件
1.官网看效果,看文档
2.过程,css,js 盒子
根据类名实例js对象,设置分页和大盒子,大盒子要over hidden
文档看配置文件的属性设置,延迟时间等其他参数
增删改查案例
1.减少dom操作,数据推动视图,增删改数据,每次数据变化根据数据遍历插入li (给父元素tbody 增加子元素 appendchild) 插入前先清空html=‘’ 否则会在原先的基础上多出,插入li时给一个自定义属性id标识,后续事件委托根据这个值删除元素
2.验证表单思路,遍历所有的表单 根据name来,然后获得n个表单域的数据,遍历只要有一个为空则提示
BOM
1.bom>dom , window.document===document
js执行机制
1.单线程 (浏览器多线程,归纳js的异步待处理任务,时间到推回js同步执行栈处理)
2.同步任务主线程执行,有一个执行栈
3.异步通过回调实现
- click,resize,load,error, 定时器和掩饰其,添加到任务(消息)队列中
4.事件循环——获得,执行,再获得任务执行,称之为事件循环
location对象
1.href跳转页面,支付成功1秒后跳转回首页 定时器+倒计时。 search拿请求参数
reload刷新 等于f5 参数为true强制刷新 等于ctrl + f5
hash 获取#后面部分
navigator对象
1.获取浏览器相关信息
拿到代理查看是什么打开的,安卓或者苹果则跳转另一个手机适配的网站
立即执行函数的另一种写法
直接加一个叹号
history对象
本地存储
1.大小5M,多窗口共享数据,键值对存储
2.存对象需先转为json字符串,否则显示Object ——JSON.stringify 取用js.parse
3.案例改造, 逻辑中断 localstorage|| [] 备选方案
字符串拼接新方法
map
1.遍历处理 返回新数组 ,foreach没返回值
join
1.将数组的每一个元素用什么拼接成新元素join(‘’)没参数则逗号分隔有空字符串’'参数则则没有分隔符
案例改造
1.map遍历所有对象,根据对象属性值拼串返回一个新的数组值,最后数组内的每一个元素变成每一个的li然后join(‘’)拼接植入
2.form注册提交事件,内部使用this.reset()进行重置表单域的内容
3.删除业务使用事件委托,否则给按钮注册的话找不到最新的新增,也就是无法动态的给新来的数据按钮注册点击事件 (可能新来的数据 事件委托没有及时的检测到?)
4.判断点击的是A标签也就是删除按钮,获取e对象,身上的自定义属性id,且该id为map遍历自带的形参index,然后用splice给他移除掉
5.删除后再新增,判断stuId不应该为length 而是最后一条的id+1,否则会出现id重复的情况 数组【length-1】.id获取
如果没有最后一条数据则为1,三元判断
这里不使用逻辑中断因为及时length没有会是一个undefined 直接报错
正则
1.表单验证。敏感词替换,提取内容
2.语法定义。 使用语法,检测/替换/提取字符串
test方法返回t/f
exec返回数组
小兔鲜案例
1.change事件改变之后调用检测函数,返回t/f 后续表单验证检测
- 使用属性选择器拿到表单
3.按钮的勾选按钮使用toggle切换,有勾选样式就删,没有就加
4.最后提交表单域统一调用函数,根据返回值来决定是否提交表单
一个是change检查,一个是提交检查
5.账号or二维码登录,事件委托拿到e,登基思想高亮,内容则循环然后根据e的自定义属性id索引来确定 哪个content要显示 ,也是登基,全隐藏后遍历找到再显示
6.登录成功后首页显示,就是结构准备好 兄弟元素获取两个li,一个用来展示用户,一个用来给点击退出登录
,然后 渲染函数开局调用,获取本地存储的直根据结构替换掉内容就行,模板字符串
退出就删存储,重新渲染
放大镜案例
业务分析
1.经过盒子列表,左侧切换。 经过图片,右侧放大镜效果
2.拿到三个盒子,小/中/大 使用mouseOver事件,因为有冒泡。判断触发类型img让里面的img冒泡上来并且拿到src,放到中盒子上
3.监听的父盒子一般使用this。来配合登基思想
4.移入中/大盒子,大盒子显示 离开时隐藏,内部加一个定时器200ms后隐藏
事件内的函数不加小括号,否则就变成立即执行了
5.在中盒子里添加移动事件,计算在中等盒子里的left和top值
获取鼠标在视口的left和top(pageX)坐标和盒子在视口的坐标getBinding.left,pageX-getBindingClientRect().left 得到鼠标在盒子中的距离
6.遮罩层的x,y设置为二者相减的值,不过这里的盒子距离左和上是针对窗口的,此时要减去到时候可以要scrollTop的距离,当下滚时,卷起来的距离变大,getBindingClientRect().Top变为0 pageY-0此时pageY会变大,因为pageY是鼠标在html文档中的距离,,因此还需要减去卷起来的距离
7.x,y小于黑盒子一半时不动,且大于 总宽度-黑盒子一半时不动
8.x,y要减去自身的一半。将其定位到盒子的中心位置,且大于300时使盒子的起点-100,这样鼠标就永远保持在盒子的中间
9.大图的背景图片2倍放大了,因此中图走1px大图要走2px才能走到同样的位置,且是反着走的,可以想象大图相当于镜头前的一群人,要看他的右边区域得让着一群人整体往左移动
JS进阶
作用域
1.块作用域 es6后新增的。var没有块级作用域概念 let和const会产生块级作用域
2.作用域链就是变量查找机制,优先当前作用域,没有的话依次找父级作用域直到全局
子能看父,父拿不到子变量
垃圾回收机制
1.变量,函数 开辟内存空间
2.赋值操作就是读写内存,如果不使用了局部变量就回收,全局不回收只能关闭销毁
3.内存由于某种原因未释放或者无法释放占用就叫内存泄漏,类似于一个人造反管不住了泄露了
4.堆栈空间分配区别
栈:操作系统自动分配,变量函数
堆,程序员分配,若不释放,由垃圾回收机制回收,复杂类型放堆
5.算法。引用和标记计数法
引用:每被用到1次就+1.清空所有变量的引用 x=null则释放
嵌套引用,两个局部变量的堆地址互相引用
标记
1.全局作用域开始,顺着线能发现对象的就标记不回收
闭包
1.理解为,一个函数A里面有一个函数B,且里面的那个函数B使用到了A的变量。至少有内外函数 内函数用外函数的变量 且内函数要被外函数调用,也就是一个普通的函数套一个外函数锁死了变量范围,且该函数要立即执行
将变量锁在函数里,不污染全局变量
2.外部使用内部函数的变量,外部函数将内部函数返回出去,且最外部调用这个外部函数相当于调用了内部函数,而内部函数能使用外部函数,等同于全局作用域访问外部函数的变量
相当于闭包内的函数拿了外部函数变量给的调用外部函数的外部使用,通过一个有权限访问外部函数的函数传递即可
3.使用场景,变量私有化,然后通过函数调用改变变量,不让别人乱搞
变量提升
1.提升声明在最前面,实际开发用let const先声明在访问
函数提升
1.函数在声明之前调用,不报错,变量就会? ,只提升声明不提示调用,还是先声明在调用
2.只提升声明,赋值给变量不行
函数参数
动态参数
1.不确定的参数个数,相当于一个可变的伪数组,使用arguments获取
剩余参数
1.展开运算符,作为形参的剩下参数 ,箭头函数没有arguments, …用的最多
使用时不需要…
展开运算符
1.也是… 能把对象还是数组展开,不修改原数组,可以作为一个拷贝操作
2.场景,最大值,求和 …等价于1,2,3
合并
箭头函数
1.没有this,this向上查找谁是上层调用就谁是this, 更简洁,替代匿名函数的函数表达式
2.()=>{}写法 一个形参省略小括号 一行代码返回省略大括号,如果是小括号包裹大括号则隐式返回对象,没参数不省略小括号
3.没有arguments 用…args
事件用箭头,this不为事件源,而是window
4.dom事件用this则不用箭头
解构赋值
数组解构
1.获取数组的所有值,【x:100,y:200】=arr
2.将数组所有元素快速批量赋值给多个变量
3.数组开头,前有语句,加分号,否则会被当作上一条代码的末尾,不换行了
4.变量少,单元值多,单元值多了不管,或者用剩余参数
5.可以设置默认值
6.按需导入赋值
7.多维数组也能解构
对象解构
1.对象抽取属性赋值给新变量
变量必须不能在之前被声明过
可以改名, 旧名:新名
2.解构数组对象
3.多级对象解构
foreach
1.遍历数组
2.形参为每一个item和索引index, 没有返回值,加强版的for循环
3.适合遍历数组对象
渲染商品案例
1.空字符串,foreach拼接,解构,省写obj.xxx obj.aaa
2.css激活和聚焦则变色实现tab栏切换,不需要监听然后登基思想了
filter
const xx=a.filter((item)=>{return item>20})大于20的过滤返回
const xx=a.filter(item=> item>20)
标签判断,解构,箭头,过滤, 给变的做文章,不变的设置默认值,例如这里的全部区间,为所有数据,其他条件都不符合不改最终的arr就默认返回 作为全部区间
构造函数
1.类似于java的类,抽取公有属性
2.不加return。,默认返回值为新的对象,形参可以不写,写了return返回值无效
3.顺序
创建对象,this开辟新空间,形参赋值,返回
4.静态变量
直接构造函数.xxx
5.实例成员写到实例对象上 xxx赋值给this.xxx,静态成员写到构造函数上构造函数.静态成员(变量或者是函数)
6.str内置构造函数
const str=‘1234’ 为 new String (‘1234’) 简单数据类型包装为引用数据类型,身上有很多方法,例如toFixed,length
常见方法
split(‘分隔符’)字符串转数组,以啥分隔符为切割分界线
startsWith以什么开始
案例
切割,map遍历生成结构,join转串插入
7.object内置构造函数
object获取所有keys =》object.keys,数组接收
assign(目标,源头)拷贝对象
也可以来新增属性,也可以说是合并属性
8.array内置构造函数
reduce累加器
常见方法
案例
属性值,values获取,然后join(‘’)
伪数组转真数组
-
Array .from(xxx)
-
const arr=[…xxx]
9.number
toFixed(2)
判断有没有尽量用三目运算,别用if
小数直接运算会出现0.1+0.2=0.3000008精度丢失,我们先转为整数,后除前面乘过的数值
面向对象
1.功能划分,在原有的基础上改,而过程要重现所有流程,容易维护,高复用 ,封装继承多态(同一样东西,用他的最笼统的称呼,大范围覆盖了小范围,方便传递,不会类型错误,好比你一个月赚多少钱,不到10万,那这个范围就可能包括很多,可以细说也可以不细说,你是谁?,我是人,这个人也可以有很多细节,男女之分,地位之分,笼统的分类,这在参数传递时类型声明非常简洁,你不需要因为我是一个学生而变化参数类型为学生,例如 Student xxx,只需要 People xxx。然后你可以正常的调用xxx.方法,小范围的详细方法,好比,你是一个具体是谁谁谁,对外以一种笼统的身份宣称,并通行于各个符合该身份的场合,如果以一种具体的身份,则不符合大多场合,总的来说,多态能够更灵活的在代码中传递,可以的变量的赋值,也可以是形参的传递,大范围转小范围称之为向下转型,可以调用小范围身上的方法,小范围转大范围为向上转型,可以提升类型范围,流通函数之间)
原型对象
解决了new一大堆对象的内存浪费
1.类似于java里的静态对象,里的静态方法
2.每个构造函数都有原型对象,可以挂载不变的函数,实例化不占内存 共享方法
3.构造函数and原型对象的this都为实例后的对象
数组扩展方法
1.Math。max不能直接传数组,要传多个数字类型1,2,3,4 因此展开运算符
2.原型新增方法,有点类似vue
3.由于调用max()没有传arr,你要传就变成这样了arr.max(arr)麻烦。我们干脆不传。内部用…this展开arr即可
constructor属性
1.构造函数对象在原型对象里面
2.原型对象是构造函数的孩子,构造函数属性是原型对象的孩子 二者互等
修复原型指向
当我们一次性给原型对象加了很多共有方法后会覆盖原来的构造函数,必须要在里面重新指向原来的构造函数
对象原型
构造函数能访问,那实例对象怎么也能访问?
1.每个实例对象身上都有一个__proto__ 指向原型对象 二者===全等
2.里面和原型对象也有contructor属性指向构造函数
3.就是让实例对象能够通过链发现原型对象上的方法
原型继承
1.给共有属性抽为一个对象,然后加到原型对象上,就变成了继承,最后由于覆盖了原型对象,原型修复一下 就重新指回去构造函数即可
2.这样会带来一个问题,如果该原型给其他人继承了,比如man,如果想要再次往该原型添加方法,生孩子,那一动全动,影响到了man,因为地址指向同一个堆
解决方法需要使得结构用的是同一个person。但是你要修改的原型对象是不同一个,类似new 一个新的实例,这样给woman的共有方法prototype添加方法时不影响到man
将抽取出来的对象 变成构造函数,利用其实例后不同内存的特性
总结一句话**,共有部分想抽取并且以后还想改,就必须隔离,而这个隔离要用到构造函数** 就new一个共有对象给原型对象
原型链
是一个查找规则,由原型对象这个大哥来串起来所有的父子关系
1.只要是对象就有__proto,oject的__poto为空 ,原型对象可以看作是实例对象,也有一个对象原型,指向原型对象,
2.原型对象太牛逼了,又可以当作共有方法池,又起一个链接父类的作用(内部有__proto),内部还有构造函数属性指向构造函数,这样孙子可以找到曾爷爷,直到null
3.而每一个对象都有__proto,每一个原型对象里都有构造函数
4.instanceof判断是不是该类的子孙类,也就是顺着链能不能找到,是不是有血缘关系
面向对象案例
1.封装一个功能,模态框,点击后调用
①业务功能,构造函数
②挂载打开功能
③关闭方法
封装到原型对象时要用function,不用箭头,因为要使用到this,默认值,传参,创建元素,类名,子元素
挂载方法到原型上,追加当前自身调用 追加modal对象里的modalbox 然后实例后调用open即可显示modalbox
关闭方法设置在open里面,获取i标签,监听,箭头函数,因为是让modal实例对象进行close()关闭,而不是i标签,i标签可没这个方法
xxx.remove()自鲨当前盒子
优化
如果有模态框,先删再加逻辑与中断。 box&& box.remove() 满足第一个条件则remove
浅拷贝
直接赋值的是 引用地址的拷贝,指向同一份内存
1.展开/or assign, 只拷贝第一层,也就是对象内的一层属性,如果对象内还有对象,其属性命名空间不隔离
深拷贝
递归
延时模仿间歇器
递归拷贝
1.遇到数组属性,建一个空数组作为newOBj[k] 然后给其传递源头oldObj[k] ([‘苹果’,‘香蕉’]) 递归自调用
2.第二次进来for遍历oldObj将数组里的每一个元素遍历除索引值index为key,然后oldObj[key]判断为简单数据类型则放到新的数组newObj里的第几个下标索引位置
3.如果不是数组是属性那就正常赋值
lodash库
1.下js文件,引入,调方法cloneDeep
json转换器
转为json,变成简单数据类型,然后parse转为对像,在内存总多了一块属于自己的空间
异常处理
抛出一个error实例,有几行提示和错误消息
会终止程序
捕获异常
1.不中断执行
2.catch捕获,形参为error实例
finally无论如何会执行
debugger
严格模式
script下加字符串’use strict’
改变this——call
call(this谁,arg1,arg2)
apply
不一样之处是这个是传递数组,接收时要一个一个拿不能只写一个形参
可以直接传数组,这样apply,之前不行,只能一个一个或者是展开运算符
bind
1.改变this并用新变量接收函数,但是不调用,用法和call相似
使用场景
定时器的调用者是window,找不到当前事件的this,设置disable,我们需要在延时器bind切换this为btn,然后里面的this则变为btn
这里可以将btn改为this,因为外部环境的this就是btn
防抖debounce
频繁触发,不好,设置定时器
案例
1.鲁大师
2.手写
声明定时器,存变量
经过,也就是一直打断回城,那我的定时器就一直重新开始计算
如果不打断回城,回城时间一到则 定时器里调用 防抖函数
代码
1.由于防抖函数有小括号,立即执行
可以在防抖函数里做一个return,把防抖里的具体业务返回,这样一来每次鼠标移动都可以触发,可以说是把原先立即执行的防抖函数给永久生效化了
2.返回的函数内声明定时器,每次进行判断定时器是否存在,如果存在,说明正在回成,但是触发了防抖,相当于打断,将定时器清除,然后再设置一个定时器,如果定时器期间没有被打断,也就是触发防抖,那就时间一到就调用函数即可
const box = document.querySelector('.box')
let i = 0
function mouseMove() {
box.innerHTML = i++
}
function debounce(fn, time) {
let timer
return function () {
if (timer) clearTimeout(timer)
timer = setTimeout(function () {
fn()
}, time)
}
}
box.addEventListener('mousemove', debounce(mouseMove, 500))
注意,定时器不能直接加小括号,否则会立即调用,应该写一个匿名函数 持久化
不能直接覆盖,因为你只是改了引用地址而已,实际他还会堆里面,也就是说你在无限的开启定时器,而非重置
// if (timer) clearTimeout(timer)
timer = setTimeout(function () {
fn()
}, time)
节流throttle
技能冷却,重复调用必须等待指定时间后才能进行下一次调用
1.鲁大师
2.手写
思路
触发节流,如果没有定时器说明是刚来的,我们给他设置一个定时器,倒计时结束后执行fn,然后顺便清空 timer, 因为如果有定时器也就是说在冷却阶段, timer不为空则return即可,也可以不用return,就正常啥也不干就行,反之执行代码也就是技能释放这个动作困在了定时器里,只有时间到才能调用,定时器结束清空timer,下次继续设置定时器来决定使用技能也就是调用函数的时机,总结就根据timer的引用地址 判断是否结束任务
const box = document.querySelector('.box')
let i = 0
function mouseMove() {
box.innerHTML = i++
}
function throttle(fn, time) {
let timer
return function () {
if (!timer) {
timer = setTimeout(function () {
fn()
timer = null
}, time)
}
return
}
}
box.addEventListener('mousemove', throttle(mouseMove, 2000))
也可以想 上公共场所,一个人进去之后,也就是一开始!timer,厕所没人的情况,进去之后上了一把倒计时锁,timerOut,后面的人一看到!timer不符合无人条件,因为已经有锁timer了嘛,自然!timer为假,就只有灰溜溜的走了,但是当第一个人上完厕所的时候(便便排出身体这个函数执行成功了),会自己手动把锁销毁,下一个一看到!timer 没锁了就继续上了
这里为什么不使用clearTimeout而是timer=null呢,定时器开启后的函数内不能清除定时器,那只是改变了引用,那没clear的那个定时器去哪了? 标记整理法还是引用整理法,没人引用他了,被GC回收,或者是标记整理法的根节点寻着线找不着定时器也给他清除了
防抖节流总结
1.多次触发,执行一次
场景:搜索框。手机号,邮箱输入
2.多次触发,每一次触发后得等一会,
场景:mousemove,resize scroll
节流综合案例
1.视频的时间更新事件触发太快了,设置1秒1次记录,下次打开视频有观看历史记录进度 类似于ae的每隔几分钟自动保存
鲁大师
然后加载的时候改变currentTime即可