作用域(scope)
局部作用域
作用域:规定了变量生效的范围
函数作用域
在函数内部声明的变量只能在函数内部访问,外部无法直接访问
总结:
1.函数内部的变量外部无法访问
2.函数的参数也是内部的局部变量
3.不同函数之间的变量无法相互访问
4.函数执行完毕后,函数内部的变量实际被清空了
块作用域
在JS中使用{}包裹的代码块,代码块内部声明的变量外部可能无法访问
总结:
1.let声明的变量会产生代码块,var不会产生块作用域
2.const声明的变量也会产生块作用域
3.不同代码块之间无法相互访问
4.不建议使用var,因为他不产生块作用域会造成变量污染
全局作用域
<script>标签和.js文件的最外层就是全局作用域,在此声明的变量在函数内部可以访问。
window对象动态添加的属性默认为全局作用域
在函数中未使用的任何关键字声明的变量也是全局变量
尽可能少的声明全局变量,防止变量污染
作用域链
作用域链本质上是底层的变量查找机制
在函数被执行时,会优先查找当前作用域中的变量
如果当前作用域查找不到则会依次逐级查找父级作用域直至全局作用域
总结:
1.嵌套关系的作用域串联起来形成了作用域链
2.相同作用域链中按着从小到大的规则查找变量
3.子作用域能查找父级作用域,父级作用域无法查找子级作用域
垃圾回收机制
内存的生命周期
JS中分配的内存,一般有如下的生命周期:
1.内存分配:当我们声明变量函数对象的时候,系统会自动给他们分配内存
2.内存使用:即读写内存,也就是使用变量函数等
3.内存回收:使用完毕,由垃圾回收器自动回收不再使用的内存
注意:
全局变量一般不会回收
一般情况下局部变量的值,不用了,会被自动回收
内存回收:程序中分配的内存因为某种原因未释放或无法释放叫做内存泄漏
JS垃圾回收机制-算法说明
堆栈空间分配说明:
1.栈(操作系统):由操作系统自动分配释放函数的参数值,局部变量等,基本数据类型放在栈里面
2.堆(操作系统):一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收到堆里面
浏览器的回收算法:引用计数法和标记清除法
引用计数法
当一个对象变量被声明后会在栈内放一个指向堆的地址引用数加一
但是当栈内的地址被改为null后堆内的数据引用数减一为零会被自动回收
缺点:
嵌套引用
由于它们之间相互引用,引用次数永远无法为0,所以无法被自动回收,会造成大量的内存泄露
标记清除法
标记清除法的核心:从根部扫描对象,能找到的对象就是使用的,找不到的对象就是要回收的对象
闭包
概念:一个函数对周围状态的引用捆绑在一起,内层函数中访问外层函数的作用域
闭包 = 内层函数 + 外层函数的变量
闭包的作用:封闭数据,提供操作,外部也可以访问内部的变量,但是无法修改内部变量
闭包的风险:存在内存泄漏的风险
变量提升
当我们使用var去声明一个变量的时候会存在变量提升的现象
function fn() {
console.log(a)
var a = 10
}
fn() //由于var只提前声明不提前赋值所以输出变量时a未定义
变量提升的一个流程:
先把var变量提升到当前作用于的最前面
只提升变量声明,不提升变量赋值
然后依次执行代码
函数进阶
函数提升
函数提升与变量提升相似,指的是在函数被声明之前就可以被调用
fun() //调用函数
function fun() {
console.log('声明之前就可以被调用...')
}
但是用var赋值的函数表达式,不能被提前调用
fun()
var fun = function() {
console.log('函数表达式不存在提升的现象') //本质上是先声明了fun,但是并未将函数一同赋予fun
}
函数参数
动态参数
arguments是函数内部内置的伪数组没有数组的方法,只存在函数中
但是可以正常调用,传入参数,利用for循环可以一次得到传递过来的参数
//定义一个函数
function sum() {
let s = 0
for (let i = 0;i < argument.length;i++) {
sum + = argument[i]
}
console.log(s)
}
sum(2,3)
sum(1,2,4)
剩余参数(函数中使用)
1....是语法符号,至于最末函数形参之前,用于获取多余的实参
2.借助...获取的剩余实参是个真数组
function fun(a,b,...arr) {
console.log(a) //得到的是1
console.log(arr) //得到的是[3,4,5],调用的时候不加...
}
fun(1,2,3,4,5)
剩余参数主要应用场景:用于获取多余的实参
剩余参数和动态参数之间最大的区别:动态参数是伪数组
剩余参数是则真数组
展开运算符(数组中使用)
展开运算符(...),将一个数组展开
典型运用场景:求数组最大值(最小值),合并数组
求数组最值
const arr = [1,2,5,3,6,2]
console.log(Math.max(...arr))
console.log(Math.min(...arr))
合并数组
const arr1 = [1,2,3]
const arr2 = [4,5,6]
const arr3 = [...arr1,...arr2]
console.log(arr3)
箭头函数
基本语法
const fn = function(x) {
console.log(x)
} //普通的函数表达式可以用箭头表达式代替
const fn = (x) => {
console.log(x)
} //与上方的函数表达式等价
const fn = x => {
console.log(x)
} //当形参只有一个的时候()可以省略
const fn = x => console.log(x) //当代码只有一行的时候可以省略{}
const fn = x => x+x //当只有一行代码的时候可以省略return
const fn = uname => ({uanme:uname})
console.log(fn('刘德华')) //可以输出对象
总结:
1.箭头函数是函数表达式,因此不存在函数提升
2.箭头函数只有一个参数的时候可以省()
3.箭头函数只有一行代码的时候可以省略{},并自动为其做返回(return)
4.加()的函数体返回的是对象字面量
箭头函数参数
普通函数有arguments动态函数
箭头函数没有arguments动态参数,但是有剩余参数(...arr)
const getSum = (...arr) => {
let sum = 0
for (let i = 0 ; i < arr.length ; i++ ) {
sum += arr[i]
}
return sum
}
const result = getSum(1,2,3)
console.log(result)
箭头函数this
在开发过程中使用箭头函数前要考虑好函数中的this指向的值,事件回调使用箭头函数时,this为全局的window,因此DOM事件回调函数为了简便,不建议使用箭头函数。
解构赋值
数组解构
数组解构是将数组的单元值快速批量赋值给一系列变量的简洁语法
基础语法:
1.赋值运算 = 左侧 [] 用于批量声明变量,右侧数组的单元值被赋值给左侧的变量
2.变量的顺序对应数组单元值的位置依次进行赋值操作
//普通数组
const arr = [1,2,3]
//批量声明变量a,b,c并同时赋予变量值
const [a,b,c] = arr
//同时将单元值依次赋予变量
const [a,b,c] = [1,2,3]
总结:
1.数组解构赋值的作用是将数组的单元值快速批量赋值 给一系列变量的简洁写法
2.JS前面一定要写分号的两种情况:
1.立即执行函数之间
2.数组解构之前
3.变量的数量大于单元值的数量,多余的变量将被赋予undefined
4.变量的数量小于单元值的数量,可以通过剩余参数(...arr)获取剩余所有的值
对象解构
对象解构语法:
const {uname,age} = {uname:'pink老师',age:18}
console.log(uname)
console.log(age)
注意:属性名要与变量名要一致
当属性名冲突的时候要更换属性名
const uname = 'red老师'
const {uname:username,age} = {uname:'pink老师',age:18}
console.log(username)
console.log(age)
更换属性名的语法:旧属性名: 新属性名
数组对象解构:
const [{uname,age}] = [{uname:'pink老师',age:18}]
console.log(uname)
console.log(age)
注意:属性名要与变量名要一致
多级对象解构:
const person = [{
name:'佩奇',
family:{
mother:'猪妈妈',
father:'猪爸爸',
sister:'乔治'
},
age:6
}]
const [{name,family{mother,father,suster},age}]
console.log(name)
console.log(mather)
console.log(father)
console.log(sister)
console.log(age)
遍历数组forEach方法
forEach()方法用于调用数组的每个元素,并将元素返回给回调函数
语法:
被遍历的数组.forEach(function(当前数组的元素,当前元素的索引号){
函数体
})
筛选数组filter
作用:筛选数组符合条件的元素,并返回符合条间的元素组成的新数组
语法:
被遍历的数组.filter(function(item,index){
return 筛选的条件
})