前端JS进阶回顾1

作用域

作用域规定了变量能够被访问的范围。

局部作用域与全局作用域

局部作用域:函数作用域与块作用域
函数作用域:在函数内部声明的变量只能在函数内部访问,外部无法直接访问(函数执行完毕后,函数内部的变量就被清空了)
块作用域:在js中使用{}包裹的代码称为代码块,代码块内部声明的变量外部可能(var定义可被访问)无法被访问
let、const声明的变量会产生块作用域,var不会产生
全局作用域:在script标签与.js文件中为全局作用域,在其中声明的变量全局可访问

作用域链

作用域链本质上就是变量查找机制
函数被执行时会采用就近原则优先查找函数作用域中的变量,如果当前作用域无该变量则逐级查找父级作用域直至全局作用域(子能够访问父作用域,父无法访问子作用域)

JS垃圾回收机制(GC)

JS中内存的分配回收都是自动完成的,内存在不使用的时候会被垃圾回收器自动回收
内存生命周期:内存分配(声明时)->内存使用(读写内存时)->内存回收(使用完毕时)
全局变量关闭页面回收,局部变量在不使用时会自动回收
内存泄漏:程序中分配的内存由于某种原因未释放或无法释放叫做内存泄漏
垃圾回收算法:引用计数法与标记清除法
复杂数据类型的数据地址存储在栈中,数据存储在堆中,栈中的地址指向该数据(或堆内其他数据指向该数据时)称为被引用,当地址指向更改为其他数据时,原数据的引用就被减少,当无地址(或数据)指向原数据时,称为无引用
引用计数法:该对象是否存在指向它的引用,如果无引用则回收对象

1
2
3
4
1.跟着记录被引用的次数
2.如果被引用了一次,记录+1,多次引用累加
3.减少一个引用则-1
4.引用次数为0时释放内存

引用计数存在一个致命问题,嵌套引用

1
2
3
4
5
6
7
function fn(){
let o1={}
let o2={}
o1.a=o2
o2.a=o1
return '引用计数无法回收'
}

标记清除法
标记清除法是从根部(全局对象)出发定时扫描内存中的对象,能从根部到达的对象都是还需要使用的,无法触及到的对象标记为不再使用,稍后进行回收

闭包

一个函数对周围状态的引用捆绑在一起,内层函数中访问到其外层函数的作用域
闭包=内层函数+外层函数变量
作用:将内部数据返回,让外部能够使用函数内部变量,实现数据的私有

1
2
3
4
5
6
7
function fn(){
const arg=1
return function g(){
console.log(arg)
}
}
fn()

风险:可能导致内存泄漏

变量提升

变量提升是JS的缺陷,只存在var中
在代码执行之前,将var的声明提升到当前作用域最前面,但不提升赋值

1
2
console.log(arg)//return undefined
var arg=1

上述代码等效于

1
2
3
var arg
console.log(arg)//return undefined
arg=1

函数进阶

函数提升

函数提升与变量提升类似,在相同作用域下

1
2
3
4
5
fn()
function fn(){
// ...
return 0
}

函数参数

动态参数:arguments包含调用函数时传入的所有实参,返回的是伪数组

1
2
3
4
5
6
7
function getSum(){
let sum=0
for(let i=0;i<arguments.length;i++){
sum+=arguments[i]
}
return sum
}

剩余参数:用于接收形参后的多余参数,剩余参数中返回的是真数组

1
2
3
4
5
6
7
function getSum(...arg){
let sum=0
for(let i=0;i<arg.length;i++){
sum+=arg[i]
}
return sum
}

:展开运算符,可以展开数组,可以求数组最大值,合并数组等

1
2
3
const arr=[1,2,3,5]
Math.max(...arr)//return 5
const arr2=[...arr,23,5]

箭头函数

箭头函数使得函数表达式更简洁

1
2
3
4
5
6
7
8
const fn=()=>{
// ...
return 0
}
const fn1=x=>{
return x
}
const fn2=y=>y

参数:没有动态参数,只有剩余参与

1
2
3
4
5
6
7
const getSum=(...arg)=>{
let sum=0
for(let i=0;i<arg.length;i++){
sum+=arg[i]
}
return sum
}

this:在作用域的上一层沿用this

1
2
3
4
5
const fn=()=>{
return this //return window
}
const cls=document.querySelector('.cls')
cls.addEventListener('click',fn)//return e

解构赋值

解构赋值是将复杂数据类型的值依次赋予给一系列变量的简洁语法

1
2
3
4
5
6
7
const arr=[1,2,3]
const obj={
a:1,
b:2
}
const [a,b,c]=arr
const {a:d,b:e}=obj//d===obj.a

在立即执行函数和[]前必须加分号

1
2
3
let a=1
let b=2;
[b,a]=[a,b]

深入对象

字面量创建

1
2
3
const obj={
a:1
}

利用new Object创建

1
2
3
4
5
const obj=new Object()
obj.a=1
const obj1=new Object({
b:1
})

利用构造函数创建,构造函数用于初始化对象

1
2
3
4
5
function Student(name,age)=>{
this.name=name
this.age=age
}
const Jack=new Student('Jack',19)

实例化执行过程

创建新对象
构造函数this指向新对象
执行构造函数代码,修改this,添加新的属性
返回新对象

实例成员&静态成员

通过构造函数创建的对象称为实例对象,实例对象中的属性和方法称为实例成员
构造函数创建的实例对象彼此独立互不影响

构造函数中的属性和方法被称为静态成员,静态成员只能构造函数访问,静态方法中的this指向构造函数

1
2
3
4
5
6
function Student(name,age)=>{
this.name=name
this.age=age
}
Student.num=1001
console.log(Student.num)//1001

内置构造函数

JS底层对数据进行实例化,使得简单数据类型包装为复杂数据类型

Object

Object.key(obj)获取对象中的所有属性,返回一个数组
Object.values(obj)获取对象中的所有值,返回一个数组
Object.assign(newObj,oldObj)用于对象拷贝,实际上常用与对象追加,将oldObj的属性增加到newObj

Array

forEach(fn)用于遍历数组,不返回数组
filter(fn)用于过滤数组,返回符合筛选条件的新数组
map(fn)用于迭代数组,返回处理后的新数组
reduce(fn(prev,curr),init)返回累计处理的结果,init为初始值,prev为前一个值,curr为当前值,init可不传,fn返回值作为下一次循环的prev

其他常用方法
join用于拼接字符串
find查找元素,返回符合条件的第一个元素组,无则返回undefined
every检测所有元素是否符合指定条件,所有都符合返回true,否则false
some检测是否存在元素符合条件,存在返回true,否则false
concat合并两个数组,返回新数组
sort排序
splice删除或替换原数组元素
reverse反转数组
findIndex查找元素索引

String

length获取字符串长度
split(splitStr)字符串拆分为数组
substring(start,end)截取字符串
startsWith是否以某字符开头
includes判断字符是否包含,return boolean
toUpperCase转大写
toLowerCase转小写
indexOf检测包含某字符
endsWith检测是否以某字符结尾
replace替换字符串,正则
match查找字符串,正则


前端JS进阶回顾1
http://example.com/2026/03/09/前端JS进阶回顾1/
作者
印星
发布于
2026年3月9日
许可协议