目录
[1. 作用域](#1. 作用域)
[(1) 局部作用域](#(1) 局部作用域)
[(2) 全局作用域](#(2) 全局作用域)
[2. 垃圾回收](#2. 垃圾回收)
[(1) 引用计数法](#(1) 引用计数法)
[(2) 标记清除法](#(2) 标记清除法)
[3. 闭包](#3. 闭包)
[(1) 作用](#(1) 作用)
[(2) 风险](#(2) 风险)
[4. 变量提升](#4. 变量提升)
[(1) var](#(1) var)
[(2) let 和 const](#(2) let 和 const)
[(3) const](#(3) const)
[5. 函数提升](#5. 函数提升)
[(1) 函数声明](#(1) 函数声明)
[(2) 函数表达式](#(2) 函数表达式)
[6. 函数参数](#6. 函数参数)
[(1) 动态参数](#(1) 动态参数)
[(2) 剩余参数](#(2) 剩余参数)
[(3) 展开运算符](#(3) 展开运算符)
[7. 必须加分号的两种情况](#7. 必须加分号的两种情况)
[(1) 立即执行函数](#(1) 立即执行函数)
[(2) 使用数组的时候](#(2) 使用数组的时候)
[8. 箭头函数](#8. 箭头函数)
[(1) 特点](#(1) 特点)
[9. Symbol](#9. Symbol)
[10. 生成器函数](#10. 生成器函数)
[11. Promise](#11. Promise)
[12. async 和 await](#12. async 和 await)
[(1) async](#(1) async)
[(2) await](#(2) await)

1. 作用域
作用域是指变量和函数的可访问范围。
(1) 局部作用域
-
函数作用域 :在函数内部声明的变量,外部无法访问。
javascript
function foo() { var x = 10; // 函数作用域 } console.log(x); // 报错:x未定义
-
块作用域 :在大括号
{}
内部声明的变量。var
声明的变量不会产生块作用域。let
和const
声明的变量会产生块作用域。
javascript
if (true) { let y = 20; // 块作用域 } console.log(y); // 报错:y未定义
(2) 全局作用域
-
最外层声明的变量,在任何地方都可以访问。 javascript
var z = 30; // 全局作用域 function bar() { console.log(z); // 30 }
2. 垃圾回收
垃圾回收是指自动管理内存的机制,释放不再使用的内存。
(1) 引用计数法
- 已弃用。
- 通过记录对象被引用的次数来判断是否回收。
- 缺点:无法处理循环引用(两个对象相互引用),导致内存泄漏。
(2) 标记清除法
- 从全局对象(根部)开始扫描,标记所有可达的对象。
- 未标记的对象会被回收。
- 解决了循环引用的问题。
3. 闭包
闭包是指一个函数及其对周围状态的引用捆绑在一起。
(1) 作用
-
外部访问函数内部变量,实现数据私有。 javascript
function outer() { let count = 0; return function inner() { count++; return count; }; } const fn = outer(); console.log(fn()); // 1 console.log(fn()); // 2
(2) 风险
- 闭包会导致内存泄漏,因为内部函数会保留对外部函数变量的引用。
4. 变量提升
变量提升是指将变量声明提升到当前作用域的最前面。
(1) var
-
函数作用域。
-
变量提升。
-
可以重复声明。 javascript
console.log(a); // undefined var a = 10;
(2) let
和 const
-
块级作用域。
-
没有变量提升。
-
作用域内只能声明一次。 javascript
console.log(b); // 报错:b未定义 let b = 20;
(3) const
-
块级作用域。
-
必须赋初始值。
-
不能重新赋值,但可以修改数组或对象的元素。 javascript
const arr = [1, 2, 3]; arr.push(4); // 允许 arr = []; // 报错
5. 函数提升
函数声明会被提升到当前作用域的最前面。
(1) 函数声明
-
提升函数声明,但不提升调用。 javascript
foo(); // "Hello" function foo() { console.log("Hello"); }
(2) 函数表达式
-
必须先声明赋值才能调用。 javascript
bar(); // 报错:bar未定义 var bar = function() { console.log("World"); };
6. 函数参数
(1) 动态参数
-
使用
arguments
对象(伪数组)。javascript
function sum() { let total = 0; for (let i = 0; i < arguments.length; i++) { total += arguments[i]; } return total; } console.log(sum(1, 2, 3)); // 6
(2) 剩余参数
-
使用
...
获取多余实参(真数组)。javascript
function sum(...nums) { return nums.reduce((a, b) => a + b); } console.log(sum(1, 2, 3)); // 6
(3) 展开运算符
-
展开数组,不会修改原数组。 javascript
const arr1 = [1, 2]; const arr2 = [3, 4]; const merged = [...arr1, ...arr2]; // [1, 2, 3, 4]
7. 必须加分号的两种情况
(1) 立即执行函数
javascript
(function() {
console.log("IIFE");
})();
(2) 使用数组的时候
javascript
const arr = [1, 2, 3];
[].push.apply(arr, [4, 5]);
8. 箭头函数
(1) 特点
-
this
是静态的,指向声明时的作用域。 -
不能作为构造函数实例化对象。
-
不能使用
arguments
对象。javascript
const add = (a, b) => a + b; console.log(add(1, 2)); // 3
9. Symbol
-
类似字符串的第七种基本数据类型。
-
值是唯一的。
-
不能与其他数据进行运算。
-
不能遍历。 javascript
const id = Symbol("id"); const obj = { [id]: 123 }; console.log(obj[id]); // 123
10. 生成器函数
-
用于异步编程。 javascript
function* generator() { yield 1; yield 2; } const gen = generator(); console.log(gen.next().value); // 1
11. Promise
-
封装异步操作并获取成功或失败的结果。 javascript
const promise = new Promise((resolve, reject) => { setTimeout(() => resolve("Success"), 1000); }); promise.then((result) => console.log(result)); // "Success"
12. async
和 await
(1) async
-
返回一个 Promise 对象。 javascript
async function foo() { return "Hello"; } foo().then((result) => console.log(result)); // "Hello"
(2) await
-
必须写在
async
函数中。 -
等待 Promise 完成并返回结果。 javascript
async function bar() { const result = await Promise.resolve("World"); console.log(result); // "World" } bar();