type
status
date
slug
summary
tags
category
icon
password
作用域和作用域链
局部作用域
函数作用域
- 在函数内部声明的变量,只能在函数内部被访问,函数外部无法访问函数内容的变量
- 函数的参数也是函数内部的局部变量
- 不同函数内部声明的变量无法互相访问
- 函数执行完以后,函数内部的变量实际被清空了
块作用域
let const
声明的变量会产生块作用域,var
不会
- 不同代码块之间的变量不能互相访问
- 推荐使用
let const
全局作用域
<script>
标签 和 .js文件
的 最外层 就是所谓的全局作用域,在此声明的变量在函数内部也可以被访问,其他作用域都可以被访问- 为window对象动态添加的属性默认也是全局,不推荐
- 函数中未使用任何关键词声明的变量也是全局变量,不推荐
- 尽可能少用全局变量,防止全局变量被污染
作用域链
本质就是底层的 变量查找机制
- 在函数被执行的时候,会优先查找当前函数作用域中查找变量
- 如果当前作用域查不到变量,会依次逐级查找父级作用域直到全局作用域
- 子作用域能够访问父作用域,父作用域不能访问子作用域
JS垃圾回收机制和算法
垃圾回收机制(Garbage Collection) 简称 GC
JS中内存的分配和回收都是自动完成的,内存不适用的时候会被垃圾回收器自动回收
内存的生命周期:
- 内存分配: 当我们声明变量、函数、对象的时候,系统会自动分配内存
- 内存使用: 读写内存,也就是访问变量、函数等
- 内存回收: 使用完毕,由垃圾回收器自动回收不再使用的内存
说明:
- 全局变量一般不会回收(关闭页面回收)
- 一般情况下局部变量的值,不用了会自动回收
内存泄漏: 程序中分配的内存由于某种原因程序未释放或无法释放叫做内存泄漏
引用计数: 看一个对象是否有指向它的引用,没有引用了就回收
但是当对象相互引用时会造成循环嵌套引用,导致无法内存回收,内存泄漏,所以现在不用引用计数法
标记清除:从根部(在JS中就是全局对象)出发,定时扫描内存中的对象。凡是能从根部到达的对象都是需要使用的,无法从根部出发触及到的对象,被标记为不再使用,稍后回收
JS闭包
概念:一个函数对周围引用的状态捆绑在一起,内存函数中访问到外层函数的作用域
简单理解:闭包 = 内层函数 + 外层函数的变量
闭包的应用:数据的私有
闭包的危险:内存泄漏
变量和函数提升
变量提升
允许在变量声明前即被访问(仅存在var声明变量的情况)
注意:
- 变量在未声明之前即被访问,会报语法错误
- 变量在 var 声明之前即被访问,变量的值为
undefined
let / const
不存在变量提升
- 变量提升出现在相同作用域当中
函数提升
会把所有的函数声明提升到当前作用域的最前面
函数剩余参数和展开运算符
动态参数:
arguments
是函数内置的伪数组变量,包含了调用函数时传入的所有实参剩余参数:
使用
...arr
方式获取剩余的参数,而且获取的是真数组ES6箭头函数的使用
普通函数有
arguments
动态参数箭头函数没有,但是有剩余参数
...args
箭头函数不会创建自己的this,只会从自己的作用域链的上一层沿用this
在dom事件回调函数中,不推荐使用箭头函数,因为此时this会指向全局的window
数组解构
对象解构
如果解构出来的名字和全局已有的变量名冲突,可以给解构出来的对象名改名,格式:
旧变量名:新变量名
多级对象解构,需要指明解构的二级对象是哪一个
构造函数
构造函数是一种特殊函数,用来初始化对象
两个约定:
- 命名以大写字母开头
- 他们只能通过
new
操作符来执行
说明:
- 使用
new
关键字调用函数的行为称为实例化
- 实例化构造函数时没有参数可以省略()
- 构造函数内部无需写
return
,返回值即为新创建的对象
- 构造函数内部的
return
返回的值无效
new Object() new Date()
也是实例化构造函数
new实例化执行过程
实例化的过程:
- 创建新对象
- 构造函数this指向新对象
- 执行构造函数代码,修改this,添加新的属性
- 返回新对象
基本包装类型
内置构造函数:Object Array String Number
基本数据类型:字符串 数值 布尔 undefined null
我们虽然是基本数据类型但是可以使用Number的方法,因为js底层在我们初始化的时候就做了包装,
let num = new Number(10)
所以可以调用