1、作用域、解构、箭头函数
1.1作用域
1.1.1局部作用域
函数作用域和块作用域
1)函数作用域
只能在函数内部被访问
2)块作用域
被{}包裹的代码成为代码块,代码块内部声明的变量外部有可能无法被访问
1.1.2全局作用域
< script>和.js文件的最外层就是所谓的全局作用域
1.1.3作用域链
作用域链本质上市底层的变量查找机制
1)在函数执行时,优先查找当前函数作用域中查找变量
2)如果当前作用域查找不到则会依次逐级查找父级作用域直到全局作用域
1.1.4js垃圾回收机制
1.1.5闭包
1.1.6变量提升
1)把所有var声明的变量提升到当前作用域的最前面
2)只提升声明,不提升赋值
1.2 函数进阶
1.2.1函数提升
会把所有函数声明提升到当前作用域最前面
只提升函数声明,不提升函数调用
1.2.2函数参数
除了实参、形参,还有动态参数arguments(本质是伪数组。只存在函数中)、剩余参数
剩余参数:
function getSum(...arr){
console.log(arr)
}
getSum(1)
getSum(1,2)
//...是语法符号,置于最末函数形参之前,用于获取多余的实参,且获得的剩余实参,是个真数组,可以使用pop,push等方法
function getSum(a,b...arr){
console.log(arr)
}
展开运算符:…
写在外面的叫展开运算符,就不是叫剩余参数了,剩余参数是在函数中使用的。
展开运算符用于求数组最大/小值,合并数组
const arr = [1,2,3]
console.log(Math.min(...arr))
//合并数组
const arr = [1,2,3]
const arr2 = [4,5,6]
const arr3 = [...arr,...arr2]
console.log(arr3)
1.2.3箭头函数
es6新增,使函数表达式更简洁
箭头函数更适用于替代需要匿名函数的地方,
箭头函数不存在函数提升
1)基本语法
//1、
const fn = ()=>{
}
fn()
//2、只有一个形参,可以把小括号去掉
const fn = x=>{
}
//3、只有一行代码的时候,可以省略大括号
const fn = x=> console.log(x)
//4、只有一行代码,无需return,直接返回结果
const fn = x=>x+x
//5、箭头函数可以直接返回一个对象
const fn = uname=>({uname:uname})
2)箭头函数参数
箭头函数没有arguments
const getSum = (...arr)=>{
let sum=0
for(){
}
return sum
}
getSum(1,2,3,4)
3)this
//1、以前的this指向,谁调用这个函数,this就指向谁
//2、箭头函数不会创建自己的this,只会从自己的作用域链的上一层沿用this
//3、对象方法的箭头函数
const obj = {
sayHi:()=>{
console.log(this)//指向window
}
}
const obj = {
sayHi:function(){
const count = ()=>{
console.log(this)//指向obj,这应该看它的上级块作用域,且上一级的块作用域必须是函数,因为函数才有this
}
}
}
注意:
<1>DOM事件的回调函数不推荐使用箭头函数,特别是需要用到this的时候
<2>事件回调函数使用箭头函数,this为全局的window
1.3 解构赋值
知道解构的语法及分类,使用解构简洁语法快速为变量赋值
1.3.1数组解构
将数组的单元值快速批量赋值给一系列变量的简洁语法
const arr = [100,60,80]
const [max,min,avg] = arr
console.log(max)
//也可以这样写
const [max,min,avg] = [100,60,80]
交换变量
let a = 1
let b = 2;
[a,b]=[b,a]
console.log(a,b)
// 变量
const [a,b,c] = [1,2,3]//单元值
1)变量多,单元值少,undefined
2)变量少,单元值多
3)剩余参数 变量少,单元值多
4)为了防止有undefined传递单元值的情况,可以设置默认值
const [a = '手机',b = '华为']=['小米']
console.log(a)//小米
console.log(b)//华为
5)按需导入赋值
const [a,b,,d]=[1,2,3,4]
console.log(d)
6)支持多维数组结构
const [a,b,[c,d]]=[1,2,[3,4]]
*加分号的两种情况
1、立即执行函数
2、使用数组开头的时候
1.3.2 对象解构
1)
const {uname,age} = {uname:'pink老师',age:18}
console.log(uname)
console.log(age)
还可以对对象解构的变量名更改为新变量名
const {uname:username,age} = {uname:'pink',age:18}
console.log(username)
2)解构数组对象
const pig=[
{
uname:'11',
age:6
}
]
const [{uname,age}] = pig
console.log(uname)
console.log(age)
3)多级对象解构
获得ajax传过来的Msg,是json对象。
foreach
不返回数组,不写return,适合遍历数组对象
1.4综合案例
filter
2、构造函数、数据常用函数
2.1深入对象
2.1.1创建对象
1)字面量
2)new Object({})
3)构造函数
2.1.2构造函数
构造函数目的是用来快速创建多个类似对象的
function Pig(name,age,gender){
this.name = name
this.age = age
this.gender = gender
}
const Peppa = new Pig('yhx',6,'nv')
new关键字调用函数的行为是:实例化
2.1.3实例成员&静态成员
2.2内置构造函数
引用类型:
Object、Array、RegExp、Date
包装类型:
String、Number、Boolean等
2.2.1Object
2.2.2Array
reduce
当数组是对象数组时,应该使用下列代码,且reduce的第二个参数必须要写,写0
2.2.3String
2.2.4Number
2.3购物车综合案例
处理购物车中的赠品显示:
购物车案例
3、深入面向对象
3.1 编程思想
3.1.1面向过程介绍
就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现,使用的时候再一个一个的依次调用就可以了。
3.1.2面向对象介绍(oop)
面向对象程序开发思想中,每一个对象都是功能中心,具有明确分工。
面向对象编程具有灵活性、代码可复用、容易维护和开发的优点,更适合多人合作的大型软件项目。
面向对象的特性:封装性、继承性、多态性
3.1.3概括,面向对象和面向对象的优缺点
面向过程编程:
优点:性能比面向对象高,适合跟硬件联系很紧密的东西,例如单片机就采用的面向对象编程。
缺点:没有面向对象易维护、易复用、易扩展。
面向对象:易维护、易复用、易扩展,由于面向对象有封装、继承、多态性的特性,可以设计出低耦合的系统,使系统更加灵活、更易于维护。
缺点:性能比面向过程低
3.2构造函数
构造函数体现了面向对象的封装特性。
构造函数实例创建的对象彼此独立、互不影响。
构造函数中的方法在每次实例化对象的时候都会在内存的堆中存放每个实例化对象的方法,会浪费内存,可以采用原型,开解决这个问题。
3.3原型
3.3.1原型
①原型:是一个对象。
②原型的作用是:1)共享方法2)可以把那些不变的方法,直接定义在prototype对象上
③构造函数和原型对象里面的this指向实例化的对象
3.3.2constructor属性
下列代码给出如何防止修改后的原型对象constructor就不在指向当前构造函数,可以在修改后的原型对象中,添加一个constructor指向原型对象。
3.3.3对象原型
3.3.4原型继承
继承有原型继承、组合式继承,这里讲的是原型继承。
将Preson写成构造函数,即可实现Woman的原型中有baby函数,而Man原型中没有baby函数。
如果不使用new Preson()而使用preson对象赋值,会导致Woman和Man的原型中都有baby函数,因为对Woman修改原型,也就是在堆中的preson对象中修改,而Man指向的也是这个被修改的preson对象,所有Man的原型一起被改了。
3.3.5原型链
对象都有_proto_属性
只要是原型对象都要constructor
instanceof
万物皆对象
3.4综合案例
4、高阶技巧
4.1深浅拷贝
1)浅拷贝
浅拷贝缺点:
2)深拷贝
①递归实现深拷贝
面试:
1、深拷贝就是做到拷贝出来的对象不会影响被拷贝的对象,要想实现深拷贝,就要用到函数递归。
2、普通对象直接赋值就可以,但是对象是数组,再次调用这个函数递归就可以了。
3、如果遇到的是对象形式,再次利用递归把对象解决。
那就是先array后对象o
②lodash
③json
4.2异常处理
1)throw抛异常
2)try /catch捕获异常
catch中没有throw,要记得写return
3)debugger![在这里插入图片描述](https://img-blog.csdnimg.cn/f16171be0e8e4234b44364547ef350be.png)
4.3处理this
1)this指向
①普通函数的this
例子:
②箭头函数的this
注意:
总结:
2)改变this
①call()
②apply()
它跟call不一样的地方就是,形参是以数组的形式传的。
用apply实现求数组最大/小值:(也可以使用展开元素符求)
③bind()
实现定时器中改变this指向:
总结:
4.4性能优化
4.4.1防抖debounce
单位时间内,频繁触发事件,只执行最后一次。
使用场景:
1)只需要用户最后一次输入完,在发送请求。
2)手机号、邮箱验证输入检测
实现方法:
1)lodash提供的防抖来处理_.debounce(,)
2)手写一个防抖函数来处理
分成4步:
4.4.2 节流 throttle
单位时间内,频繁触发事件,只执行一次
例子:技能冷却
使用场景:
高频事件:鼠标移动mousemove、页面尺寸缩放resize、滚动条滚动scroll等等
实现方法:
1)lodash提供的节流函数来处理
2)手写一个节流函数来处理
分3步
注意:setTimeout无法使用clear清除定时器
4.4.3 防抖和节流 throttle总结
4.5综合案例