JavaScript 基础与 ES6+ 新特性
大约 3 分钟
JavaScript 基础与 ES6+ 新特性
JavaScript 是 Web 开发的核心语言。ES6 (ECMAScript 2015) 及其后续版本引入了大量新特性,极大地提升了开发效率和代码可读性。
变量声明 (let & const)
ES6 引入了 let 和 const 来替代 var。
let: 块级作用域,不存在变量提升,不允许重复声明。const: 块级作用域,声明常量,一旦声明必须初始化,且值不能重新赋值(但对象属性可修改)。
// var 的问题:变量提升,没有块级作用域
if (true) {
var a = 10;
}
console.log(a); // 10
// let 的块级作用域
if (true) {
let b = 20;
}
// console.log(b); // ReferenceError: b is not defined
// const 常量
const PI = 3.14159;
// PI = 3.14; // TypeError: Assignment to constant variable.
const person = { name: "Alice" };
person.name = "Bob"; // OK: 修改对象属性是允许的
Symbol (基本数据类型)
ES6 引入的原始数据类型,表示独一无二的值。常用于定义对象属性名,避免冲突。
const s1 = Symbol('foo');
const s2 = Symbol('foo');
console.log(s1 === s2); // false
const obj = {
[s1]: 'Hello'
};
console.log(obj[s1]); // Hello
// Symbol 属性不会出现在 for...in、Object.keys() 中
箭头函数 (Arrow Functions)
箭头函数提供了一种更简洁的函数写法,并且不绑定自己的 this。
// 传统写法
const sum = function(a, b) {
return a + b;
};
// 箭头函数
const sumArrow = (a, b) => a + b;
// 箭头函数的 this
const obj = {
name: "MyObj",
sayHello: function() {
setTimeout(() => {
console.log(`Hello from ${this.name}`); // this 指向 obj
}, 1000);
}
};
obj.sayHello();
解构赋值 (Destructuring Assignment)
允许按照一定模式,从数组和对象中提取值,对变量进行赋值。
// 数组解构
const [x, y] = [1, 2];
console.log(x, y); // 1 2
// 对象解构
const user = { id: 1, name: "John", age: 30 };
const { name, age } = user;
console.log(name, age); // John 30
// 参数解构与默认值
function printUser({ name, age = 18 }) {
console.log(`User: ${name}, Age: ${age}`);
}
printUser({ name: "Tom" }); // User: Tom, Age: 18
模板字符串 (Template Literals)
使用反引号 `` 定义,支持多行字符串和内嵌变量。
const name = "World";
const greeting = `Hello,
${name}!`;
console.log(greeting);
展开语法 (Spread Syntax) ...
用于数组合并、对象复制等。
// 数组合并
const arr1 = [1, 2];
const arr2 = [...arr1, 3, 4]; // [1, 2, 3, 4]
// 对象合并/浅拷贝
const obj1 = { a: 1 };
const obj2 = { ...obj1, b: 2 }; // { a: 1, b: 2 }
Set 和 Map 数据结构
Set
类似于数组,但成员的值都是唯一的,没有重复的值。
const s = new Set([1, 2, 3, 4, 4]);
console.log([...s]); // [1, 2, 3, 4] (去重)
s.add(5);
s.has(1); // true
s.delete(2);
Map
类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
const m = new Map();
const o = {p: 'Hello World'};
m.set(o, 'content');
console.log(m.get(o)); // "content"
m.has(o); // true
m.delete(o);
WeakSet 和 WeakMap
- WeakSet: 成员只能是对象,且是弱引用(不计入垃圾回收机制)。
- WeakMap: 键必须是对象,键名是弱引用。常用于深拷贝解决循环引用、DOM 节点元数据存储。
剩余参数 (Rest Parameters)
用于获取函数的多余参数,替代 arguments 对象。
function sum(...numbers) {
return numbers.reduce((prev, curr) => prev + curr, 0);
}
console.log(sum(1, 2, 3)); // 6
模块化 (Modules)
使用 import 和 export 进行模块化开发。
// math.js
export const add = (a, b) => a + b;
export default function multiply(a, b) {
return a * b;
}
// main.js
import multiply, { add } from './math.js';
console.log(add(1, 2));
console.log(multiply(3, 4));
可选链 (Optional Chaining) ?.
安全地访问嵌套对象的属性。
const user = { address: { street: "Main St" } };
console.log(user?.address?.street); // Main St
console.log(user?.contact?.phone); // undefined (不会报错)
空值合并运算符 (Nullish Coalescing) ??
只有当左侧为 null 或 undefined 时,才返回右侧的值。
const count = 0;
const num = count || 10; // 10 (因为 0 是 falsy)
const num2 = count ?? 10; // 0 (只有 null/undefined 才会取默认值)
Proxy 和 Reflect (元编程)
Proxy
用于修改某些操作的默认行为,等同于在语言层面做出修改,属于一种“元编程”(meta programming)。
const handler = {
get: function(target, propKey, receiver) {
console.log(`Getting ${propKey}!`);
return Reflect.get(target, propKey, receiver);
},
set: function(target, propKey, value, receiver) {
console.log(`Setting ${propKey}!`);
return Reflect.set(target, propKey, value, receiver);
}
};
const obj = new Proxy({}, handler);
obj.count = 1; // Setting count!
++obj.count; // Getting count! -> Setting count!
Reflect
将 Object 对象的一些明显属于语言内部的方法(如 Object.defineProperty),放到 Reflect 对象上。与 Proxy handler 的方法一一对应。
Loading...
