1.闭包以及应用场景:
闭包=内层函数+外层函数的变量
表现形式:函数之间相互嵌套
内层函数能够访问到外层函数的变量
作用:延长变量的生命周期,能够使函数外部访问到函数内部的变量(实现数据私有)
缺点:会使内存泄漏
1.1通过闭包的形式统计执行次数
functionfn(){
leti=0
functioninner(){
i++
console.log(`函数执行调用了${i}次`)
}
retureninner
}
constresult=fn()
result()//函数执行调用了1次
result()//函数执行调用了2次
result()//函数执行调用了3次
2.作用域链
1)作用域链本质是底层的变量查找机制
2)函数执行是优先在当前作用域查找变量,如果没有会逐层向上级作用域查找,直到全局作用域
3.垃圾回收机制
垃圾回收机制简称GC
1)在JS中内存的分配和回收都是自动完成的,内存在不使用时会被垃圾回收器自动回收
2)不了解垃圾回收机制很容易造成内存泄漏(就是用不到的内存,没有及时释放会造成内存泄漏)
3.1内存的生命周期
1)内存分配:声明变量、函数、对象时系统会自动给他们分配内存
2)内存使用:操作这些变量、函数、对象就是使用内存
3)内存回收:使用完毕后,垃圾回收器自动回收不再使用的内存
注意:
全局变量一般不会被回收,只有关闭页面的时候才会被回收
局部变量不使用就会被自动回收
3.2常见的浏览器垃圾回收算法(引用计数法、标记清除法)
3.2.1引用计数法
看一个对象是否有指向它的引用
算法:
1)跟踪记录每个值被引用的次数
2)这个值被引用一次,就会记录次数1
3)多次引用会累加
4)减少引用会使记录次数减1
5)引用次数为0时,释放内存
3.2.2标记清除法
核心:
1)标记清除法将‘不再使用的对象’定义为‘无法到达的对象’
2)就是从根部(JS的全局对象)出发定时扫描内存中的对象,凡是能从根部到达的对象都是还需要使用的
3)那些无法从根部到达的对象标记为不在使用,会被回收器自动回收
4.let,const和var的区别
1)let声明的变量会产生块级作用域,var不会
2)let声明的变量不挂载再window对象上,var声明的变量时挂载再window对象上的
3)let声明的变量不存在变量声明的提升,var声明的变量存在,但是只提升声明,不提升赋值
4)const声明常量,不可以更改赋值
5)实际开发中推荐先声明在访问变量
5.函数的参数
5.1动态参数(arguments)
arguments是函数内部内置的伪数组变量,它包含调用时传入的所有实参
// 需求:定义一个函数,求任意数的和
function getSum(){
console.log(arguments)
let sum = 0
for(let i=0; i<arguments.length; i++){
sum+=arguments[i]
}
console.log(sum)
}
getSum(1,2,3,6,4,8,6)//30
getSum(2,36,7,4,1)//50
//1)arguments是一个伪数组,只存在于函数中
//2)arguments的作用是动态获取函数的实参
//3)可以通过for循环遍历到传递过来的实参
5.2剩余参数
语法:function 函数名(...变量名){}
注意:
1)在函数内部使用的时候直接使用变量名
2)剩余参数的位置必须在函数所有参数的最后一个位置
值:是一个真数组,可以调用数组的方法包含的是函数调用时候剩余的实参
// 需求:定义函数,求任意数的和
function getSum(...arrs){
console.log(arrs)
let sum = 0
for(let i = 0; i<arrs.length; i++){
sum+=arrs[i]
}
console.log(sum)
}
getSum(1,2,3,4,5,6,7,8,9)//45
--------------------------------------------------------------
function fn(a,b,...arrs){
console.log(arrs);
}
fn(5,6)//[]
fn(1,2,3,5,4)//[3,5,4]
fn(12,54,26,98)//[26,98]
5.3展开运算符(数组的展开运算符)
语法:...数组名
作用:展开数组
经典应用场景:
1)合并数组
2)求数组的最大值和最小值(使用Math.max()方法、使用Math.min()方法)
3)对象的拷贝(浅拷贝)
//展开数组
let arr = [10,2,3,4]
console.log(...arr);//10 2 3 4
-----------------------------------------------
//合并数组
let arr = [10,2,3,4]
let arr2 = [33,66,45,99]
// 第一种方法
let arr3 = [...arr,...arr2]
console.log(arr3);//[10, 2, 3, 4, 33, 66, 45, 99]
//第二种方法
console.log(arr.concat(arr2))//[10, 2, 3, 4, 33, 66, 45, 99]
-------------------------------------------------------
// 求最大值和最小值
let max = Math.max(...arr,...arr2)
let min = Math.min(...arr,...arr2)
console.log(max,min);//99 2
-------------------------------------------------------
// 使用展开运算符进行对象的拷贝
let obj = {name:123,age:12,loc:12,}
let o = {...obj}
console.log(obj);//{name: 123, age: 12, loc: 12}
console.log(o);//{name: 123, age: 12, loc: 12}
6.箭头函数
箭头函数的基本语法:基本语法:let xxx= ()=>{}
注意:箭头函数里面有没有arguments
this指向window
let fn = () =>{
consloe.log(11)
}
----------------------------------------------------
//改造箭头函数
let fn = (a,b) =>{
console.log(a+b)//3
}
fn(1,2)
-------------------------------------------------------
//简写1:如果箭头函数的参数只有一个,那么()可以省略
let fn= a =>{
console.log(a)
}
fn(123)
---------------------------------------------------------
//简写2:如果箭头函数的参数只有一行代码,那么{}可以省略
let fn = a => console.log(a)
fn(123)
---------------------------------------------------------
//简写3:如果箭头函数的参数只有一行代码,并且使用return返回函数的结果,那么{}和return都可以省略
let sum = (a,b) => a+b
const aa = sum(1,2)
console,log(aa)
------------------------------------------------------------
//简写4:如果箭头函数的参数只有一个对象,并且return返回的是一个对象,那么{}和return可以省略,但对象需要加上()
let fn = () =>({name:'aa',age:18})
console.log(fn)
7.多维数组和多级对象如何解构
7.1多维数组解构:
语法:let(var、const)[变量名1,变量名2,...]=[元素1,元素2,...]
作用:将数组中的元素快速批量赋值给一系列的变量的简写操作
结果:是将数组的元素按照位置一一对应赋值给左边的变量
//经典应用场景 交换两个数
let a = 10
let b = 20
[b,a] = [a,b]
console.log(a,b)//20 10
-----------------------------------------------------------
//变量名多,数组元素少会出现undefined的情况
let [a,b,c,d] = [1,2,3]
console.log(a,b,c,d)//1 2 3 undefined
------------------------------------------------------------
//避免出现undefined的情况可以设置默认值
let [a,b,c,d=0] = [1,2,3]
console.log(a,b,c,d)//1 2 3 0
------------------------------------------------------------
//变量名少,数组元素多会剩余元素,使用剩余参数
let [a,b,c,...arrs] = [1,2,3,4,5,6,7,8,9]
console.log(a,b,c,arrs)//1 2 3 [4,5,6,7,8,9]
---------------------------------------------------------------
//按需导入,忽略某些返回值
let arr = [1,2,3,4,5,6]
let [a,,b,c] = arr
console.log(a,b,c)//1 3 4
7.2多级对象结构:
语法: 第一种情况: 对象解构变量名要和属性名保持一致
let {属性名,属性名}={属性名:属性值,属性名:属性值,...}
结果:是按照属性名进行解构所以变量名可以互换位置
第二种情况: 对象解构变量名和属性名不一致的情况
let {属性名:别名,属性名1:别名1,...}={属性名:属性值,属性名1:属性值,...}
结果:是按照属性名进行解构,所以变量名可以互换位置
let obj = {
name: "zs",
age: 18,
};
//第一种情况: 对象解构变量名要和属性名保持一致
let { na