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