JavaScript 语法技巧
这里记录了很多JavaScript的神奇技巧,会持续更新…
1. 解构赋值
解构赋值语法是一种允许你将数组或对象中的数据“解压”到独立变量中的表达式。
把解构想象成你收到了一个“礼品篮”(对象或数组)。你不需要整个篮子,你只想拿出其中的几样东西(属性或元素),并给它们分别贴上标签(变量名)。解构就是帮你自动完成这个“拿出并贴标签”过程的语法。
对象解构 (Object Destructuring)
这是最常用的解构形式,用于从对象中提取属性。
const user = {
id: 42,
name: 'Alice',
age: 25,
address: {
city: 'Wonderland'
}
};
// 1. 基本用法
const { name, age } = user;
console.log(name); // 'Alice'
console.log(age); // 25
// 2. 赋给新的变量名
const { name: userName, age: userAge } = user;
console.log(userName); // 'Alice'
// 3. 提供默认值
const { country = 'Unknown' } = user;
console.log(country); // 'Unknown'
// 4. 嵌套解构
const { address: { city } } = user;
console.log(city); // 'Wonderland'
数组解构 (Array Destructuring)
数组解构根据元素的位置进行提取。
const fruits = ['Apple', 'Banana', 'Cherry', 'Date'];
// 1. 基本用法
const [first, second] = fruits;
console.log(first); // 'Apple'
console.log(second); // 'Banana'
// 2. 跳过元素
const [ , , third] = fruits;
console.log(third); // 'Cherry'
// 3. 剩余元素 (Rest Syntax)
const [mainFruit, ...otherFruits] = fruits;
console.log(mainFruit); // 'Apple'
console.log(otherFruits); // ['Banana', 'Cherry', 'Date']
2. 展开语法与剩余参数 (…)
...
运算符根据其使用场景,既可以作为“展开语法”使用,也可以作为“剩余参数”使用。它的核心思想是“展开”与“收集”。
展开语法 (Spread Syntax):展开
展开语法将一个可迭代对象(如数组、字符串)或对象“展开”成多个独立的元素或属性。
想象一下,你把一盒卡牌(数组)从盒子里倒出来,摊在桌面上,变成一张张独立的卡牌(多个元素)。
// 1. 在数组中使用:合并与复制
const arr1 = [1, 2];
const arr2 = [3, 4];
const combined = [...arr1, ...arr2, 5]; // [1, 2, 3, 4, 5]
const copied = [...arr1]; // [1, 2] (浅拷贝)
// 2. 在对象中使用:合并与复制
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const mergedObj = { ...obj1, ...obj2 }; // { a: 1, b: 2, c: 3, d: 4 }
// 如果有同名属性,后面的会覆盖前面的
const updatedObj = { ...obj1, b: 99 }; // { a: 1, b: 99 }
// 3. 在函数调用中使用
const numbers = [1, 2, 3];
console.log(Math.max(...numbers)); // 等同于 Math.max(1, 2, 3)
剩余参数 (Rest Parameters):收集
在函数定义中,...
可以将所有剩余的参数“收集”到一个真正的数组中。
想象一下,在派对上,主持人先介绍了两位主宾(前两个参数),然后指着剩下所有的人说:“以及其余各位(剩余参数)!”
function sum(first, second, ...others) {
console.log('First:', first);
console.log('Second:', second);
console.log('Others:', others); // others 是一个真数组
return others.reduce((acc, val) => acc + val, first + second);
}
console.log(sum(1, 2, 3, 4, 5));
// First: 1
// Second: 2
// Others: [3, 4, 5]
// Result: 15
这比使用老旧的、类数组的 arguments
对象要现代和方便得多。
3. 函数参数的增强
默认参数 (Default Parameters)
你可以直接为函数参数指定默认值,当调用时未提供该参数或传入 undefined
时,将使用默认值。
function greet(name = 'Guest', greeting = 'Hello') {
console.log(`${greeting}, ${name}!`);
}
greet('Alice'); // "Hello, Alice!"
greet(); // "Hello, Guest!"
在函数参数中使用解构
这是一个非常强大且常见的模式,尤其是在处理配置对象时。
// 不使用解构
function printUser(user) {
console.log(`Name: ${user.name}, Age: ${user.age}`);
}
// 使用解构
function printUserDestructured({ name, age, country = 'USA' }) {
console.log(`Name: ${name}, Age: ${age}, Country: ${country}`);
}
const user = { name: 'Bob', age: 42 };
printUserDestructured(user); // "Name: Bob, Age: 42, Country: USA"
这种方式使函数签名更具自描述性,调用者无需关心参数对象的顺序。
4. 简化对象和属性访问
属性值缩写 (Shorthand Properties)
当你想创建一个对象,且其属性名与你用来赋值的变量名相同时,可以只写一次。
const name = 'Charlie';
const age = 35;
// 老方法
const personOld = { name: name, age: age };
// 缩写
const personNew = { name, age };
console.log(personNew); // { name: 'Charlie', age: 35 }
可选链操作符 (?.)
在尝试访问深层嵌套的对象属性时,如果中间某个属性不存在(为 null
或 undefined
),代码会立即抛出 TypeError
。可选链 ?.
解决了这个问题。
它就像在一条不确定的路上探索。每到一个岔路口(属性),你都先问一句“这里有路吗?”(
?.
)。如果没有,你就停下来并报告“此路不通”(undefined
),而不是一头栽进沟里(抛出错误)。
const user = {
name: 'David',
// address 属性缺失
};
// 老方法,需要冗长的检查
const cityOld = user && user.address && user.address.city;
console.log(cityOld); // undefined
// 使用可选链
const cityNew = user?.address?.city;
console.log(cityNew); // undefined (代码更简洁,且不会抛错)
// 也可用于函数调用
const admin = { getName: () => 'Admin' };
const regularUser = {};
console.log(admin.getName?.()); // 'Admin'
console.log(regularUser.getName?.()); // undefined
空值合并操作符 (??)
在提供默认值时,逻辑或操作符 ||
会将所有“假值”(如 0
, ''
, false
)都视为无效而使用默认值,这有时并非我们所愿。
空值合并操作符 ??
更为精确:只有当左侧的值为 null
或 undefined
时,才会返回右侧的默认值。
let score = 0;
// 使用 || 的问题:0 被视为无效,错误地使用了默认值
const finalScore1 = score || 100;
console.log(finalScore1); // 100 (错误!)
// 使用 ?? 的正确行为:0 是一个有效值
const finalScore2 = score ?? 100;
console.log(finalScore2); // 0 (正确!)
let username = '';
const displayName = username ?? 'Guest';
console.log(displayName); // '' (正确!)