文章目录
1. 作用域
1.1 作用域链
作用域链本质上是底层的变量查找机制。
- 在函数被执行时,会优先查找当前函数作用域中查找变量
- 如果当前作用域查找不到则会依次逐级查找父级作用域直到全局作用域
总结:
- 嵌套关系的作用域串联起来形成了作用域链
- 相同作用域链中按着从小到大的规则查找变量
- 子作用域能够访问父作用域,父级作用域无法访问子级作用域
1.2 闭包
个函数对周围状态的引用捆绑在一起,内层函数中访问到其外层函数的作用域
简单理解:闭包 = 内层函数 + 外层函数的变量
闭包作用:封闭数据,提供操作,外部也可以访问函数内部的变量
1.3 变量提升
变量提升是 JavaScript 中比较“奇怪”的现象,它允许在变量声明之前即被访问(仅存在于var声明变量)
注意:
- 变量在未声明即被访问时会报语法错误
- 变量在var声明之前即被访问,变量的值为 undefined
- let/const 声明的变量不存在变量提升
- 变量提升出现在相同作用域当中
- 实际开发中推荐先声明再访问变量
变量提升是什么流程?
- 先把var 变量提升到当前作用域于最前面
- 只提升变量声明, 不提升变量赋值
- 然后依次执行代码
2. 函数进阶
2.1 函数提升
函数提升与变量提升比较类似,是指函数在声明之前即可被调用。
总结:
- 函数提升能够使函数的声明调用更灵活
- 函数表达式不存在提升的现象
- 函数提升出现在相同作用域当中
2.2 函数参数
1. 动态参数
arguments 是函数内部内置的伪数组变量,它包含了调用函数时传入的所有实参
//求和
function sum(){
let s = 0
for (let i = 0; i < arguments.length;i++)
{
s +=arguments[i]
}
console.logs(s)
}
sum(5,10)
sum(1,2,4)
总结:
- arguments 是一个伪数组,只存在于函数中
- arguments 的作用是动态获取函数的实参
- 可以通过for循环依次得到传递过来的实参
2. 剩余参数
剩余参数允许我们将一个不定数量的参数表示为一个数组
- … 是语法符号,置于最末函数形参之前,用于获取多余的实参
- 借助 … 获取的剩余实参,是个真数组
function config(baseURL,...other){
console.log(baseURL) //'https://www.baidu.com'
console.log(other) //['get','json']
}
config('https://www.baidu.com', 'get', 'json')
3. 展开运算符
展开运算符(…),将一个数组进行展开
典型运用场景: 求数组最大值(最小值)、合并数组等
const arr = [1,5,3]
console.log(Math.max(...arr)) //5
const arr1 = [1,2,3]
const arr2 = [4,5,6]
const arr3 = [...arr1,...arr2]
console.log(arr3) //[1,2,3,4,5,6]
剩余参数:函数参数使用,得到真数组
展开运算符:数组中使用,数组展开
2.3 箭头函数
目的:引入箭头函数的目的是更简短的函数写法并且不绑定this,箭头函数的语法比函数表达式更简洁
使用场景:箭头函数更适用于那些本来需要匿名函数的地方
箭头函数属于表达式函数,因此不存在函数提升
1. 基本语法
语法1: 基本写法
const fn =function(){
console.log('我是普通函数')
}
fn()
const fn = ()=>{
console.log('我是箭头函数')
}
语法2:只有一个参数可以省略小括号
const fn = x =>{
return x + x
}
console.log(fn(1)) //2
语法3:如果函数体只有一行代码,可以写到一行上,并且无需写 return 直接返回值
const fn = (x,y) => x + y
console.log(fn(1,2))
//更简洁写法
form.addEventListener('click',ev => ev.preventDefault())
语法4:加括号的函数体返回对象字面量表达式
const fn1 = uname => ({uname: uname})
console.log(fn1('小嘉老师')) //{uname:'小嘉老师'}
2. 箭头函数参数
- 普通函数有arguments 动态参数
- 箭头函数没有 arguments 动态参数,但是有 剩余参数 …args
const getSum = (...agrs) => {
let sum = 0
for (let i = 0; i < agrs.length; i++) {
sum += agrs[i]
}
return sum
}
console.log(getSum(1, 2, 3)) //6
3. 箭头函数this
箭头函数不会创建自己的this,它只会从自己的作用域链的上一层沿用this。
console.log(this) //此处为window
const sayHi = () =>{
console.log(this) //window
}
btn.addEventListener('click',()=>{
console.log(this) //window
})
const obj = {
name: '小嘉',
sleep: () => {
console.log('this') //window
}
}
obj.sleep()
const obj = {
name: '小嘉',
sleep: function(){
console.log('this') //obj
}
}
obj.sleep()
const obj ={
name: '小嘉老师',
sleep:function () {
console.log(this) //obj
const fn =()=>{
console.log(this) //obj
}
fn()
}
}
obj.sleep()
在开发中【使用箭头函数前需要考虑函数中 this 的值】,事件回调函数使用箭头函数时,this 为全局的 window,因此
DOM事件回调函数为了简便,还是不太推荐使用箭头函数
//普通函数,此时this指向DOM对象btn
btn.addEventListener('click', function (e) {
console.log(this)
});
//箭头函数,此时this指向window
btn.addEventListener('click',()=>{
console.log(this)
})
3. 解构赋值
解构赋值是一种快速为变量赋值的简洁语法,本质上仍然是为变量赋值。
3.1 数组解构
基本语法:
- 赋值运算符 = 左侧的 [] 用于批量声明变量,右侧数组的单元值将被赋值给左侧的变量
- 变量的顺序对应数组单元值的位置依次进行赋值操作
const arr = [1,2,3]
const [a,b,c] = arr
典型应用:交互2个变量
let a = 1
let b = 3; //必须有分号
[b, a] = [a, b]
console.log(a) //3
console.log(b) //1
JS前面必须有分号的情况:
1. 立即执行函数
(function t(){ })();
//or
;(function t(){ })()
2. 数组解构
//数组开头的,特别是前面有语句的一定注意加分号
;[b, a] = [a, b]
- 变量多 单元值少的情况:
变量的数量大于单元值数量时,多余的变量将被赋值为 undefined
- 变量少 单元值多的情况:
const [a,b,c] =[1,2,3,4]
//a = 1
//b = 2
//c = 3
- 利用剩余参数解决变量少 单元值多的情况:
剩余参数返回的还是一个数组
const [a,b,...tel] =[1,2,3,4,5]
a = 1
b = 2
tel = [3,4,5]
- 防止有undefined传递单元值的情况,可以设置默认值
允许初始化变量的默认值,且只有单元值为 undefined 时默认值才会生效
const [a = 1,b = 2] = [3]
//a = 3
//b = 2
- 按需导入,忽略某些返回值
const [a,,b,c,d] =[1,2,3,4,5]
//a = 1
//b = 3
- 支持多维数组的结构
const [a,b] = [1,[2,3]]
//a = 1
//b = [2,3]
const [a,[b,c]] = [1,[2,3]]
//a = 1
//b = 2
//c = 3
3.2 对象解构
基本语法:
- 赋值运算符 = 左侧的 {} 用于批量声明变量,右侧对象的属性值将被赋值给左侧的变量
- 对象属性的值将被赋值给与属性名相同的变量
- 注意解构的变量名不要和外面的变量名冲突否则报错
- 对象中找不到与变量名一致的属性时变量值为 undefined
const user ={
name : '小嘉',
age : 18
}
const [name,age] = user
给新的变量名赋值:
可以从一个对象中提取变量并同时修改新的变量名
const user ={
name : '小嘉',
age : 18
}
const {name: uname, age} = user
//uname:小嘉
//age:18
冒号表示“什么值:赋值给谁”
多级对象解构:
const pig = {
name: '佩奇',
family: {
mother: '猪妈妈',
father: '猪爸爸',
sister: '乔治'
},
age: 6
}
const {name,family:{mother, father,sister} } = pig
4. forEach
forEach() 方法用于调用数组的每个元素,并将元素传递给回调函数
被遍历的数组.forEach(function(当前数组元素,当前数组索引){
//函数体
})
- forEach 主要是遍历数组
- 参数当前数组元素是必须要写的, 索引号可选
5. 筛选数组 filter 方法
filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素
被遍历数组.filter(function(currentValue,index){
return 筛选条件
})
- filter() 筛选数组
- 返回值:返回数组,包含了符合条件的所有元素。如果没有符合条件的元素则返回空数组
- 参数:currentValue 必须写, index 可选
- 因为返回新数组,所以不会影响原数组