Javascript进阶
作用域
分类
- 局部
- 函数 ==>执行完变量被清空
- 块 ==>用{}包住 ==>有可能被无法访问 【用var声明的变量】
- 全局 ==> 在script标签和.js文件最外层进行声明
作用域链
最底层的变量查找机制 ==> 在函数被执行时,会优先查找当前函数作用域中查找变量,找不到再找父级作用域
垃圾回收机制 Garbage Collection
JS中内存的分配和回收都是自动完成的
内存的生命周期
内存分配–>内存使用 -->内存回收
全局变量一般不会回收,直至关闭页面
内存泄漏
程序中分配内存未释放或无法释放由于某种原因
JS垃圾回收机制 - 算法说明
堆和栈
- 栈:操作系统自动分配函数参数及局部变量【基本数据类型】
- 堆:由程序员分配释放,或者通过垃圾回收机制【复杂数据类型】
引用计数法【基本不使用了】
若对象无指向它的引用,进行回收
[!NOTE]
设置count变量来保存对于某变量的引用次数,引用一次自增,减少引用自减,当count变为0,释放内存
引用的意思是是否有变量名或者指针保存复杂数据类型变量的地址
若复杂数据类型互相指向,则count永不为0,导致内存泄漏
标记清除法
从根部(即
闭包 - closure
简单理解:内层函数 use–> 外层函数变量
作用
封闭数据,提供操作,外部也可以访问函数内部的变量
闭包机制
function folder() {
let a = 1
function fn() {
console.log(a)
}
fn()
}
folder()
效果为
右边的Closure就是所谓的闭包
Local:局部变量
Global:全局变量
常见闭包形式
function outer() {
let a = 1
function inner() {
console.log(a);
}
return inner;
}
let b = outer();
b(); // 1
[!IMPORTANT]
相当于外部函数可以调用inner()函数,间接使用到,修改到函数内部变量,但不会让外部直接堆变量进行修改
借此实现数据的私有。 但由于始终可以查找到变量,导致变量无法被释放,产生内存泄漏的问题
变量提升
允许变量声明之前被访问(var声明变量)
const和let声明的变量不会出现这种情况
内部会先检查有无var声明的变量,若有,则将声明提前,赋值不会提前
console.log(a); // undefined
var a = 10;
console.log(a); // 10
函数进阶
函数提升
函数在声明之前可以被调用(在同等作用域下,提到最前面)
若被调用的函数为赋值得到的,则不可行,因为变量提升只提升声明,不含赋值
// 函数提升
fn()
function fn() {
console.log('函数提升')
}
// 变量提升
fun()
var fun = function () {
console.log('变量提升')
}
函数参数
动态参数
函数内置 arument
- 伪数组
- 只存在函数中
调用时有参数,定义时括号内无参数
function addAll() {
let sum = 0;
for (let i = 0; i < arguments.length; i++) {
sum += arguments[i];
}
return sum;
}
console.log(addAll(1, 2, 3, 4, 5)); //15
console.log(addAll(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)); //55
剩余参数
将不定数量的多余实参变为一个真数组
function sum(a, b, ...rest) {
let result = a + b;
for (let i = 0; i < rest.length; i++) {
result += rest[i];
}
return result;
}
console.log(sum(1, 2, 3, 4, 5)); // 15
console.log(sum(1, 2)); // 3
console.log(sum(1, 2, 3, 4, 5, 6)); // 21
展开运算符
...
将数组展开(或者对象等)
应用:
- 求数组最大组 --Math.max()
- 合并数组
const arr = [1, 2, 3, 4, 5]
console.log(...arr)
console.log(Math.max(...arr))
console.log(Math.min(...arr))
const arr1 = [1, 2, 3, 4, 5]
const arrAll = [...arr1, ...arr]
console.log(...arrAll)
箭头函数
以更简洁的方式写匿名函数
语法技巧
- 只有一个参数,可以省略括号
- 函数只有一行代码可以省略大括号
- 只有一句return语句,可省略return
- 可用来返回对象
// 箭头函数
const add = (a, b) => {
console.log(a + b);
return a * b
}
add(2, 3); // 5
const double = a => a * 2;
double(3); // 6
const item = (uname) => ({ name: uname })
console.log(item('John'))
// {name: 'John'}
只可以用剩余参数
const all = (...arr) => console.log(...arr);
all(1, 2, 3, 4, 5); // 1 2 3 4 5
不会创建自己的this,只会从自己的作用域的上一层沿用this
回调函数不推荐使用箭头函数
//this指向
const a1 = () => this
console.log(a1()); // window
const a2 = function () {
let i = 1
const a3 = () => this
console.log(a3()); // window
}
a2();
const obj = {
uname: "shaly",
sayName: () => this
}
console.log(obj.sayName()) // shaly
const obj2 = {
uname: "shaly",
sayName: function () {
const a4 = () => this
console.log(a4())
}
}
console.log(obj2.sayName())