这里写目录标题
一级目录
二级目录
三级目录
一、作用域
1.局部作用域
分为函数作用域和块作用域
函数作用域:(在函数内部声明的变量只能在函数内部被访问,外部无法直接访问)
- 函数内部声明的变量,在函数外部无法被访问
- 函数的参数也是函数内部的局部变量
- 不同函数内部声明的变量无法互相访问
- 函数执行完毕后,函数内部的变量实际被清空了
块作用域:(在javaScript中使用{}包裹的代码称为代码块,代码块内部声明的变量外部将[有可能]无法被访问)
- let声明的变量会产生块作用域,var不会产生块作用域
- const声明的常量也会产生块作用域
- 不同代码块之间的变量无法互相访问
- 推荐使用let或const
2.全局作用域
注意:
- 为window对象动态添加的属性默认也是全局的,不推荐
- 函数中未使用任何关键字声明的变量为全局变量,不推荐
- 尽可能少的声明全局变量,防止全局变量被污染
3.作用域链
作用域链本质上是底层的变量查找机制
在函数被执行时,会优先查找当前函数作用域中查找变量
如果当前作用域查找不到则会依次逐级查找父级作用域直到全局作用域
总结:
- 嵌套关系的作用域串联起来形成了作用域链
- 相同作用域链中按着从小到大的规则查找变量
- 子作用域能够访问父作用域,父级作用域无法访问子级作用域
4.js垃圾回收机制(Garbage Collection)简称GC
js中内存的分配和回收都是自动完成的,内存在不使用的时候会被垃圾回收器自动回收
内存的生命周期:
- 内存分配:当我们声明变量、函数、对象的时候,系统会自动为他们分配内存
- 内存使用:即读写内存,也就是使用变量、函数等
- 内存回收:使用完毕,由垃圾回收器自动回收不再使用的内存
说明:
全局变量一般不会回收(关闭页面回收)
一般情况下局部变量的值,不用了,会被自动回收掉
内存泄漏:
程序中分配的内存由于某种原因程序未释放或无法释放叫做内存泄漏
浏览器垃圾回收算法:引用计数法、标记清除法
引用计数法
IE采用的引用计数算法,定义“内存不再使用”,就是看一个对象是否有指向它的引用,没有引用了就回收对象
算法:
- 跟踪记录被引用的次数
- 如果被引用了一次,那么就记录次数1,多次引用会累加++
- 如果减少一个引用就减1-
- 如果引用次数是0,则释放内存
存在问题:嵌套引用(循环引用)
如果两个对象相互引用,尽管他们已不再使用,垃圾回收器不会进行回收,导致内存泄露。
function fn(){
1et o1={}
let o2 ={}
o1.a=02
o2.a=01
return'引用计数无法回收'
}fn()
因为他们的引用次数永远不会是0。这样的相互引用如果说很大量的存在就会导致大量的内存泄露
标记清除法
核心:
- 标记清除算法将“不再使用的对象”定义为“无法达到的对象”。
- 就是从根部(在js中就是全局对象)出发定时扫描内存中的对象。凡是能从根部到达的对象,都是还需要使用的。
- 那些无法由根部出发触及到的对象被标记为不再使用,稍后进行回收。
5.闭包
闭包=内层函数+外层函数的变量
作用:封闭数据,提供操作,外部也可以访问函数内部的变量
基本格式:
function outer(){
let a=10//实现了数据私有,不能随意更改
function fn(){
console.log(a)
}
return fn
}
const fun=outer()
fun()
可能引起问题:内存泄漏
6.变量提升
变量提升是js中比较“奇怪”的现象,它允许在变量声明之前即被访问(仅存在于var声明变量)
把所有var声明的变量提升到当前作用域的最前面,只提升声明,不提升赋值
二、函数进阶
1.函数提升
js会把所有函数声明提升到当前作用域的最前面,只提升函数声明,不提升函数调用
注意:函数表达式必须先声明赋值再调用,否则报错
2.函数参数
动态参数arguments:
函数内部内置的伪数组变量,它包含了调用函数时传入的所有实参
//求和函数,计算所有参数的和
function sum(){
let s =0
for(let i 0;i<arguments.length;i++){
s +=arguments[i]
}
console.log(s)
//调用求和函数
sum(5,10)//两个参数
sum(1,2,4)/两个参数
总结:
- arguments是一个伪数组,只存在于函数中
- arguments的作用是动态获取函数的实参
- 可以通过fo循环依次得到传递过来的实参
剩余参数:用于获取多余实参,在函数参数中使用
将一个不定数量的参数表示为一个数组
- …是语法符号,置于最末函数形参之前,用于获取多余的实参
- 借助…获取的剩余实参,是个真数组
function config(baseURL,…other){
console.log(baseURL)
console.log(other)//[‘get’,‘json’]
//调用函数
config(‘http://baidu.com’,‘get’,‘json’);
展开运算符…可以展开数组
求数组最大(小)值Math.max(…arr)
合并数组arr=[…arr1,…arr2]
3.箭头函数
- const fn=(形参)=>{}箭头函数 const fn=function(){}原来
目的:引入箭头函数的目的是更简短的函数写法并且不绑定this,箭头函数的语法比函数表达式更简洁
使用场景:箭头函数更适用于那些本来需要匿名函数的地方
属于表达式函数,因此不存在函数提升
只有一个形参可以省略小括号,只有一行代码时可以省略大括号和return
//更简洁的语法
const form document.queryselector('form')
form.addEventListener('click',ev =>ev.preventDefault())
箭头函数可以直接返回一个对象
const fn=(uname)=>({uname:uname})//返回的是对象
fn(‘刘德华’)
2. 箭头函数参数
普通函数有arguments动态参数
箭头函数没有arguments动态参数,但是有剩余参数…arr
3. 箭头函数this
箭头函数不会创建自己的thiS,它只会从自己的作用域链的上一层沿用this。
对象方法的箭头函数this指向window
对象方法内的箭头函数this指向对象本身
三、解构赋值
1.数组解构:将数组的单元值快速批量赋值给一系列变量的简洁语法
基本语法:
- 赋值运算符=左侧的[]用于批量声明变量,右侧数组的单元值将被赋值给左侧的变量
- 变量的顺序对应数组单元值的位置依次进行赋值操作
;[b,a]=[a,b]快速交换两个变量
注意:
立即执行函数和数组解构必须加; - 变量多单元值少,后面为undefined
- 变量少单元值多,利用剩余参数解决
const [a,b,…c]=[1,2,3,4] - 防止有undefined传递单元值可以设置默认值
- 按需导入可以忽略某些值
const [a,b,,d]=[1,2,3,4]//d=4 - 支持多维数组的结构
const [a,b,[c,d]]=[1,2,[3,4]]
2.对象解构
对象解构是将对象属性和方法快速批量赋值给一系列变量的简洁语法
基本语法:
- 赋值运算符=左侧的}用于批量声明变量,右侧对象的属性值将被赋值给左侧的变量
- 对象属性的值将被赋值给与属性名相同的变量
- 注意解构的变量名不要和外面的变量名冲突否则报错
- 对象中找不到与变量名一致的属性时变量值为undefined
- 可以给新的变量名赋值 什么值:赋值给谁
const {name:uname,age}=user
3.数组对象解构
4.多个对象解构
const pig={
name:'佩奇',
family:
mother:'猪妈妈',
father:'猪爸爸',
sister:'乔治'
},
age:6
}
//多级对象解构const {name,family:{mother,father,sister}}=pig