JavaScript进阶
- 1.作用域
- 2.箭头函数
- 3.解构赋值
- 4.Object的静态方法
- 5.Array数组的实例方法
- 1.forEach ,遍历数组,不返回数组,常用于查找遍历数组元素
- 2.fifter ,过滤数组,返回新数组,返回的是筛选满足条件的数组元素
- 3.map ,迭代数组,返回新数组,返回的是处理之后的数组元素,想要使用返回的新数组
- 4.reduce ,累计器,返回累计处理的结果,常用于求和等
- 5.join,数组元素拼接为字符串,返回字符串
- 6.find查找元素,返回符合测试条件的第一个数组元素值,如果没有符合条件的就返回undefined
- 7.every检测数组所有元素是否都符合指定条件,如果所有元素都通过检测返回true,否组返回false
- 8.some检测数组中的元素是否满足指定条件,如果数组中有元素满足条件返回true,否则返回false
- 9.concat合并两个数组,返回生成新数组
- 10.sort对原数组单元值排序
- 11.splice删除或替换原数组单元,第1个参数为起始下标,第2个为删除个数,第3个为要增加的数据。
- 12.reverse反转数组
- 13.findIndex查找元素的索引值
- 14.slice切片的意思,根据传入的起始和终止下标,获取该范围数组。
- 6.伪数组转换为真数组
- 7.String常见实例方法
- 1.实例属性length用来获取字符串长度
- 2.split('分隔符')用来将字符串拆分成数组
- 3.substring(需要截取的第一个字符的索引[,结束的索引号])用于字符串截取
- 4.startsWith(检测字符串[,检测位置索引号])检测是否以某字符开头
- 5.includes(搜索的字符串[,检测位置索引号])判断一个字符串是否包含在另一个字符串中,根据情况返回t或f
- 6.toUpperCase用于将字母转换成大写
- 7.toLowerCase用于将字母转换成小写
- 8.indexOf检测是否包含某字符
- 9.endsWith检测是否以某字符结尾
- 10.replace用于替换字符串,支持正则匹配
- 11.match用于查找字符串,支持正则匹配
- 8.Number
- 9.面向对象编程
- 10.原型(原型对象)prototype
- 11.对象原型__proto__
- 12.原型继承
- 13.原型链以及instanceof运算符
- 14.浅拷贝
- 15.深拷贝
- 16.this指向
- 17.改变this指向
- 18.防抖
- 19.节流
1.作用域
作用域规定了变量能够被访问的范围
声明变量推荐使用let或者const
2.箭头函数
箭头函数是用来代替匿名函数的
当只有一个形参时,可以省略参数括号
const fn=x=>{
console.log(x)
}
//等同于
const fn=(x)=>{
console.log(x)
}
当箭头函数只有一行代码时,可以省略大括号,并且不用写return
const fn(x)=>{
console.log(x)
}
//等同于
const fn(x)=>console.log(x)
可以返回一个对象
const fn=uname=>({name:uname})
console.log(fn('小布'))
3.解构赋值
数组解构
const arr=[20,50,89]
//数组解构赋值
const [a,b,c]=arr
//等同
const a=arr[0]
const b=arr[1]
const c=arr[2]
对象解构
const user={
name:'小明',
age:18
}
在解构赋值时,声明的变量必须与对象内属性名相同
const {name,age}=user
4.Object的静态方法
1.获取对象的所有属性名
const o={name:'小红',age:18}
console.log(Object.key(o))//['name','age']
2.获取对象的所有属性值
const o={name:'小红',age:18}
console.log(Object.values(o))//['小红',18]
3.对象的拷贝(给对象添加属性)
const o={name:'小红',age:18}
const oo={}
Obgect.assign(oo,o)
console.log(oo)//{name:'小红',age:18}
常用于给对象追加一个新键值对
Obgect.assign(o,{sex:'女'})
console.log(o)//{name:'小红',age:18,sex:'女'}
5.Array数组的实例方法
1.forEach ,遍历数组,不返回数组,常用于查找遍历数组元素
2.fifter ,过滤数组,返回新数组,返回的是筛选满足条件的数组元素
3.map ,迭代数组,返回新数组,返回的是处理之后的数组元素,想要使用返回的新数组
4.reduce ,累计器,返回累计处理的结果,常用于求和等
//语法
const arr=[1,5,8]
arr.reduce(function(){},初始值)
arr.reduce(function(上一次值,当前值){},初始值)
//示例
//1.没有初始值
const total=arr.reduce(function(prev,current){
return prev+current
})//14
//2.有初始值
const total=arr.reduce(function(prev,current){
return prev+current
},10)//24
//3.箭头函数写法
const total=arr.reduce((prev,current)=>prev+current,10)//24
//4.如果遇到的是数组对象,初始值不能省略,需要写0
const array=[
{name:'张三',
salary:1000},
{name:'李四',
salary:1000},
{name:'王五',
salary:1000}
]
const total=array.reduce((prev,current)=>{
return prev+current.salary
},0)//3000
5.join,数组元素拼接为字符串,返回字符串
6.find查找元素,返回符合测试条件的第一个数组元素值,如果没有符合条件的就返回undefined
var ages = [3, 10, 18, 20];
function checkAdult(age) {
return age >= 18;
}
function myFunction() {
document.getElementById("demo").innerHTML = ages.find(checkAdult);
}
//输出18
7.every检测数组所有元素是否都符合指定条件,如果所有元素都通过检测返回true,否组返回false
8.some检测数组中的元素是否满足指定条件,如果数组中有元素满足条件返回true,否则返回false
9.concat合并两个数组,返回生成新数组
10.sort对原数组单元值排序
const arr = [49, 5, 14, 89, 71, 3, 10];
// 一般写法
arr.sort(function (a, b) {
return a - b; // 按照升序排列
});
// 箭头函数
arr.sort((a, b) => a - b);
// 结果 [3, 5, 10, 14, 49, 71, 89]
11.splice删除或替换原数组单元,第1个参数为起始下标,第2个为删除个数,第3个为要增加的数据。
12.reverse反转数组
13.findIndex查找元素的索引值
14.slice切片的意思,根据传入的起始和终止下标,获取该范围数组。
6.伪数组转换为真数组
Array.from(arr)
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
</ul>
<script>
const lis=document.querySelectorAll('ul li')
console.log(lis)
// lis.pop()//报错
const liss=Array.from(lis)
console.log(liss)
liss.pop()
console.log(liss)
</script>
7.String常见实例方法
1.实例属性length用来获取字符串长度
2.split(‘分隔符’)用来将字符串拆分成数组
把字符串转换为数组
const str='pink,red'
const arr=str.split(',')
console.log(arr)//['pink','red']
3.substring(需要截取的第一个字符的索引[,结束的索引号])用于字符串截取
如果省略 结束的索引号 默认截取到最后
结束的索引号不包含在截取的部分(需要往后+1)
4.startsWith(检测字符串[,检测位置索引号])检测是否以某字符开头
5.includes(搜索的字符串[,检测位置索引号])判断一个字符串是否包含在另一个字符串中,根据情况返回t或f
6.toUpperCase用于将字母转换成大写
7.toLowerCase用于将字母转换成小写
8.indexOf检测是否包含某字符
9.endsWith检测是否以某字符结尾
10.replace用于替换字符串,支持正则匹配
11.match用于查找字符串,支持正则匹配
8.Number
Number是内置的构造函数,用于创建数值
常用方法:toFixed(保留几位小数)
默认保留整数,四舍五入
const price=12.345
//保留两位小数,四舍五入
console.log(price.toFixed(2))//12.35
9.面向对象编程
每一个对象都是功能中心,分工明确
面向对象的特性:封装性、继承性、多态性
10.原型(原型对象)prototype
构造函数封装的方法浪费内存,为了节约内存,使用原型对象
js规定,每一个构造函数都有一个prototype属性,指向另一个对象,所以成为原型对象
这个对象可以挂载函数,对象实例化不会多次创建原型上函数,节约内存
我们可以把那些不变的方法,直接定义在prototype对象上,这样所有对象的实例就可以共享这些方法
构造函数和原型对象中的this都指向实例化的对象
11.对象原型__proto__
对象会有一个属性__proto__指向构造函数的prototype原型对象,之所以我们对象可以使用构造函数prototype原型对象的属性和方法,就是因为对象有_proto_原型的存在
12.原型继承
//男人不能给原型对象prototype添加别的方法或属性,会影响到Perosn的原型对象prototype
const Person={
eyes:2,
head:1
}
//男人构造函数继承 想要继承Person
function Man(){
}
//通过 原型继承 Person
Man.prototype=Person
//构造函数指回Man
Man.prototype.constructor=Man
const aa=new Man()
console.log(aa)
//解决不使用同一对象,但是对象里面包含相同的属性和方法
//男人构造函数继承 想要继承Person
function Man(){
}
//通过 原型继承 Person
Man.prototype=new Person()
//构造函数指回Man
Man.prototype.constructor=Man
const aa=new Man()
console.log(aa)
//女人构造函数继承 想要继承Person
function Woman(){
}
//通过 原型继承 Person
//子类的原型=new 父类
Woman.prototype=new Person()
//给原型对象添加方法
Woman.prototype.baby=function(){
console.log('baby')
}
//构造函数指回Woman
Woman.prototype.constructor=Woman
const bb=new Woman()
console.log(bb)
13.原型链以及instanceof运算符
基于原型对象的继承使得不同构造函数的原型对象关联在一起,并且这种关联的关系是一种链状的解构,我们将原型对象的链状结构关系叫做原型链
原型链是一种查找规则,可以查找一些属性和规则,先查找当前的原型对象prototype,没有就查找上一级,也就是——proto——指向的prototype原型对象,如果还没有找到那就查找Object的原型对象,一直查找到Object为null为止
只要是 对象就有__proto__,指向原型对象
只要是 原型对象就有constructor函数,指向构造函数
构造函数.prototype.__proto__指向Object的prototype
instanceof运算符:用来查询构造函数的prototype属性是否出现在某个实例对象的原型链上
console.log(bb instanceof Person) //true
console.log(bb instanceof Object) //true
console.log(bb instanceof Array) //false
14.浅拷贝
因为直接赋值对象后修改对象属性会修改原对象的值,所以有拷贝
浅拷贝:拷贝的是地址,但是当需要拷贝的对象里面还有对象,是会有问题的(像直接复制的问题)
常见方法
1.拷贝对象:Object.assign(空对象,被拷贝的对象) / {…obj} 拷贝对象
2.拷贝数组:Array.prototype.concat() / […arr]
const obj={
name:'小红',
age:18
}
//1.直接复制,会改变原有对象的值
const o=obj
console.log(o) //{name:'小红',age:18}
o.age=20
console.log(o) //{name:'小红',age:20}
console.log(obj) //{name:'小红',age:20}
//2.浅拷贝
const o={...obj}
console.log(o) //{name:'小红',age:18}
o.age=20
console.log(o) //{name:'小红',age:20}
console.log(obj) //{name:'小红',age:18}
//2.1浅拷贝的另一种
const o={}
Object.assign(o,obj)
console.log(o) //{name:'小红',age:18}
o.age=20
console.log(o) //{name:'小红',age:20}
console.log(obj) //{name:'小红',age:18}
15.深拷贝
https://www.lodashjs.com/ 封装好的一个js库 里面有很多方法 包括深拷贝
深拷贝拷贝出来的新对象不会影响旧对象,需要用到函数递归,当我们对普通类型的对象进行拷贝时可以直接赋值,如果遇到对象里面有数组的,需要再次调用这个递归函数,如果遇到对象里包含对象,再次去调用这个递归函数处理对象,先array再对象
const obj={
name:'小红',
age:18,
hobby:['篮球','足球'],
family{
baby:'小小'
}
}
const o={}
//拷贝递归函数
function deepCopy(newObj,oldObj){
for(let k in oldObj){
//处理数组的问题 ,必须先处理数组在处理对象,因为数组也属于对象
if(oldObj[k] instanceof Arrray){
newObj=[]
deepCopy(newObj[k],oldObj[k])
}else if(oldObj[k] instanceof object){
newObj={}
deepCopy(newObj[k],oldObj[k])
}else{
//k时属性名 name,age oldObj[k]时属性值 小红 18
newObj[k]=oldObj[k]
}
}
}
使用json实现深拷贝
JSON的方法:
JSON.parse把json字符串转换为对象
JSON.stringfy把对象转换为json字符串
const obj={
name:'小红',
age:18,
hobby:['篮球','足球'],
family{
baby:'小小'
}
}
const o=JSON.parse(JSON.stringfy(obj))
16.this指向
箭头函数内不存在this,沿用上一级的
构造函数,圆形函数,dom事件函数等等,不适用箭头函数
17.改变this指向
call 和 apply 区别: call 和 apply 都是可以改变this 指向的问题, call 方法中传递参数要求一个一个传递参数。 但是apply 方法要求传递参数是一个数组形式。
bind的不同之处在于bind会返回一个新的函数。如果需要传参,需要再调用该函数并传参
call() apply() bind()
1.call()
const obj={
name='小红'
}
function fn(){
console.log(this) //this指向window
}
//call的作用 1.调用函数, 2.改变this指向
fn() //this指向window
//call(需要指向的对象,参数1,参数2)
fn.call(obj)//此时this指向obj
2.apply()
const obj={
name='小红'
}
function fn(){
console.log(this) //this指向window
}
//apply的作用 1.调用函数, 2.改变this指向 3.返回值
fn() //this指向window
//apply(需要指向的对象,[参数1,参数2])
fn.apply(obj)//此时this指向obj
3.bind()
const obj={
name='小红'
}
function fn(){
console.log(this) //this指向window
}
//bind的作用 1.不会调用函数, 2.能改变this指向 3.返回值 返回值是个拷贝原函数的函数(新函数是更改this指向的)
fn() //this指向window
//bind(需要指向的对象,参数1,参数2)
fn.bind(obj)//此时this指向obj
fn.bind(obj)(参数)
18.防抖
防抖:单位时间内,频繁触发事件,只执行最后一次
防抖函数的核心:利用setTimeout定时器来实现的
1.声明定时器变量
2.每次鼠标移动(事件触发)的时候要先判断是否有定时器,如果有先清除以前的定时器
3.如果没有定时器,则开启定时器,存入到定时器变量里面
4.定时器里面写函数调用
function debounce(fn,t){
let timer
//return 一个匿名函数
return function(){
if(timer) clearTimerout(timer)
timer=setTimerout(function(){
fn()//调用fn函数
},t)
}
}
box.addEventListener('mousemove',debounce(mouseMove,500))
19.节流
节流:单位时间内,频繁触发事件,只执行一次
节流函数的核心:利用setTimeout定时器来实现的
1.声明定时器变量
2.每次鼠标移动(事件触发)的时候要先判断是否有定时器,如果有定时器 则不开启新的定时器
3.如果没有定时器,则开启定时器,存入到定时器变量里面
3.1定时器里面调用执行的函数
3.2.定时器里面要把定时器清空
function throttle(fn,t){
let timer=null
//return 一个匿名函数
return function(){
if(!timer) {
timer=setTimerout(function(){
fn()//调用fn函数
timer=null//清空定时器
},t)
}
}
}
box.addEventListener('mousemove',throttle(mouseMove,500))
案例:播放视频,退出后重新刷新或进入展示播放进度
//1.获取元素(元素装的是视频) 要对视频进行操作
const video=document.querySelector('video')
video.ontimeupdate=_.throttle(()=>{
//console.log(video.currentTime) 获得当前视频时间
localStorage.setItem('currentTime',video.currentTime)
},1000)
//打开页面触发事件,从本地存储里面去除记录的时间,赋值给video.currentTime
video.onloadeddata=()=>{
video.currentTime=localStorage.getIiem('curentTime')||0
}