25 个JavaScript技巧:省时间,写更整洁的代码(新手到进阶)
JavaScript 一直在更新,变得越来越好用。从 ES6 开始,加入了很多新写法,能让你的代码更短、更清楚,也常常运行得更快。掌握这些技巧,不仅能让你写代码更快,还能让代码更容易让别人看懂和维护,代码质量也更好。
下面直接介绍 25 个现代 JavaScript 中很实用的技巧和写法,学会它们,写代码真的会轻松很多!
1. 三元运算符:一行搞定简单判断
用 ? : 代替简单的 if/else,代码更紧凑。// 老方法
let age = 18;
let canVote;
if (age >= 18) {
canVote = "Yes";
} else {
canVote = "No";
}
console.log(canVote); // 输出: Yes
// 新方法 (三元运算符)
let age = 18;
let canVote = (age >= 18) ? "Yes" : "No"; // 一行搞定
console.log(canVote); // 输出: Yes2. || 设置默认值:防 undefined/null
如果变量可能是 null、undefined、0、"" 或 false,用 || 给它一个后备值。// 老方法 (检查空值)
function greet(name) {
let displayName;
if (name === null || name === undefined || name === "") {
displayName = "Guest";
} else {
displayName = name;
}
console.log(`Hello, ${displayName}!`);
}
// 新方法 (|| 短路)
function greet(name) {
const displayName = name || "Guest"; // name 为假值就用 "Guest"
console.log(`Hello, ${displayName}!`);
}
greet("Alice"); // Hello, Alice!
greet(null); // Hello, Guest!
greet(""); // Hello, Guest! (注意:空字符串也被认为是假值)3. && 条件执行:满足条件才做事
用 && 只在条件为真时才执行后面的代码,适合简单的操作。// 老方法
let isAdmin = true;
if (isAdmin) {
console.log("Admin privileges granted.");
}
// 新方法 (&& 短路)
let isAdmin = true;
isAdmin && console.log("Admin privileges granted."); // 输出: Admin privileges granted.
let isGuest = false;
isGuest && console.log("Guest access."); // 没输出,因为 isGuest 是 false4. 模板字符串:拼接变量超方便
用反引号 ` 包裹字符串,里面用 ${变量} 插入变量或表达式,告别一堆加号。// 老方法 (加号拼接)
const name = "Bob";
const age = 30;
console.log("My name is " + name + " and I am " + age + " years old.");
// 新方法 (模板字符串)
const name = "Bob";
const age = 30;
console.log(`My name is ${name} and I am ${age} years old.`); // 输出: My name is Bob and I am 30 years old.5. 箭头函数:写函数更简短
写法 (参数) => 表达式 比 function 短,尤其适合做回调。注意:箭头函数没有自己的 this,它会用外面函数的 this。
// 老方法
const numbers = [1, 2, 3];
const doubled = numbers.map(function(num) {
return num * 2;
});
// 新方法 (箭头函数)
const numbers = [1, 2, 3];
const doubled = numbers.map(num => num * 2); // 一行,自动返回结果
console.log(doubled); // 输出: [2, 4, 6]
// this 的区别 (重要)
function Timer() {
this.seconds = 0;
// 普通函数:里面的 this 可能指向 window 或 undefined (严格模式)
setInterval(function() {
// console.log(this.seconds); // 错误!this 不对
}, 1000);
// 箭头函数:里面的 this 就是 Timer 实例的 this
setInterval(() => {
this.seconds++;
console.log(this.seconds); // 正确:每秒+1
}, 1000);
}
const myTimer = new Timer();6. 解构数组:快速取元素
直接从数组里把值提取到变量里,还能跳过某些元素。// 老方法
const colors = ["red", "green", "blue"];
const firstColor = colors[0];
const secondColor = colors[1];
// 新方法 (数组解构)
const colors = ["red", "green", "blue"];
const [firstColor, secondColor] = colors; // 按顺序提取
console.log(firstColor, secondColor); // 输出: red green
const [,, thirdColor] = colors; // 跳过前两个
console.log(thirdColor); // 输出: blue7. 解构对象:快速取属性
直接从对象里把属性值提取到变量里,还能给属性换名字。// 老方法
const user = { name: "Charlie", age: 25, city: "NYC" };
const userName = user.name;
const userAge = user.age;
// 新方法 (对象解构)
const user = { name: "Charlie", age: 25, city: "NYC" };
const { name, age } = user; // 提取 name 和 age
console.log(name, age); // 输出: Charlie 25
const { name: fullName, city } = user; // 把 name 提取到 fullName 变量
console.log(fullName, city); // 输出: Charlie NYC8. ... 展开数组:复制和合并
用 ... 轻松复制数组或把多个数组合成一个新数组。// 老方法
const arr1 = [1, 2];
const arr2 = [3, 4];
const copiedArr = arr1.slice(); // 复制
const combinedArr = arr1.concat(arr2); // 合并
// 新方法 (展开语法 ...)
const arr1 = [1, 2];
const arr2 = [3, 4];
const copiedArr = [...arr1]; // 复制 arr1
const combinedArr = [...arr1, ...arr2]; // 合并 arr1 和 arr2
console.log(copiedArr, combinedArr); // 输出: [1, 2] [1, 2, 3, 4]9. ... 展开对象:复制和合并
用 ... 轻松复制对象或把多个对象属性合并到一个新对象里。后面的属性会覆盖前面的同名属性。// 老方法
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const copiedObj = Object.assign({}, obj1); // 复制
const mergedObj = Object.assign({}, obj1, obj2); // 合并
// 新方法 (展开语法 ...)
const obj1 = { a: 1, b: 2 };
const obj2 = { c: 3, d: 4 };
const copiedObj = { ...obj1 }; // 复制 obj1
const mergedObj = { ...obj1, ...obj2 }; // 合并 obj1 和 obj2
console.log(copiedObj, mergedObj); // 输出: {a:1, b:2} {a:1, b:2, c:3, d:4}
// 覆盖属性
const original = { x: 1, y: 2 };
const updated = { ...original, y: 3, z: 4 }; // 覆盖 y, 添加 z
console.log(updated); // 输出: {x:1, y:3, z:4}10. ... 剩余参数:收集多个参数
函数定义时用 ...参数名,可以把传进来的多个参数自动收集到一个数组里。// 老方法 (用 arguments)
function sumAll() {
let total = 0;
for (let i = 0; i < arguments.length; i++) {
total += arguments[i];
}
return total;
}
// 新方法 (剩余参数 ...)
function sumAll(...numbers) { // numbers 是个数组
return numbers.reduce((total, num) => total + num, 0); // 用 reduce 求和
}
console.log(sumAll(1, 2, 3, 4)); // 输出: 1011. 默认参数:参数没传就用默认值
直接在函数参数后面用 = 默认值,如果调用时没传这个参数或者传了 undefined,就用默认值。// 老方法 (用 ||)
function greet(name, greeting) {
name = name || "Guest";
greeting = greeting || "Hello";
console.log(`${greeting}, ${name}!`);
}
// 新方法 (默认参数)
function greet(name = "Guest", greeting = "Hello") {
console.log(`${greeting}, ${name}!`);
}
greet(); // 输出: Hello, Guest! (两个都用默认值)
greet("Frank"); // 输出: Hello, Frank! (greeting 用默认值)
greet("Grace", "Hi"); // 输出: Hi, Grace! (都不用默认值)12. ?. 可选链:安全访问深层属性
用 ?. 访问可能不存在的对象属性(null 或 undefined),避免代码报错崩掉,返回 undefined。// 老方法 (层层检查)
const user = {
profile: {
address: {
street: "Main St"
}
}
};
let streetName;
if (user && user.profile && user.profile.address) {
streetName = user.profile.address.street;
}
console.log(streetName); // 输出: Main St
const invalidUser = {}; // 没有 profile
let invalidStreet;
// 下面如果直接访问 invalidUser.profile.address 会报错!
if (invalidUser && invalidUser.profile && invalidUser.profile.address) {
invalidStreet = invalidUser.profile.address.street; // 不会执行到这里
}
console.log(invalidStreet); // 输出: undefined
// 新方法 (可选链 ?.)
const streetName = user.profile?.address?.street; // 安全访问
console.log(streetName); // 输出: Main St
const invalidStreet = invalidUser.profile?.address?.street; // 遇到 null/undefined 就停,返回 undefined
console.log(invalidStreet); // 输出: undefined13. ?? 空值合并:只关心 null/undefined
用 ?? 判断,只有左边是 null 或 undefined 时,才用右边的默认值。和 || 不同,0、""、false 这些有效值不会被覆盖。// || 的问题 (会把 0, "", false 也当成无效值)
const count = 0;
const defaultCount_OR = count || 10; // 0 是假值,所以用了 10
console.log(defaultCount_OR); // 输出: 10 (但 0 可能是有效值)
// ?? 正确解决
const count = 0;
const defaultCount_NC = count ?? 10; // 0 不是 null/undefined,保留 0
console.log(defaultCount_NC); // 输出: 0
const emptyString = "";
const defaultString_NC = emptyString ?? "Default"; // "" 不是 null/undefined,保留 ""
console.log(defaultString_NC); // 输出: ""
const undefinedValue = undefined;
const defaultValue_NC = undefinedValue ?? "Fallback"; // undefined 是 nullish,用 "Fallback"
console.log(defaultValue_NC); // 输出: Fallback14. forEach:遍历数组每个元素
比 for 循环更简洁地遍历数组,对每个元素做点事情。// 老方法 (for 循环)
const items = ["apple", "banana", "cherry"];
for (let i = 0; i < items.length; i++) {
console.log(items[i]);
}
// 新方法 (forEach)
const items = ["apple", "banana", "cherry"];
items.forEach(item => console.log(item)); // 对每个 item 执行 console.log
// 输出:
// apple
// banana
// cherry15. map:把数组变形成新数组
遍历原数组,对每个元素进行转换,把所有转换结果放入一个新数组返回。// 老方法 (for 循环 + push)
const numbers = [1, 2, 3];
const squaredNumbers = [];
for (let i = 0; i < numbers.length; i++) {
squaredNumbers.push(numbers[i] * numbers[i]);
}
// 新方法 (map)
const numbers = [1, 2, 3];
const squaredNumbers = numbers.map(num => num * num); // 计算平方
console.log(squaredNumbers); // 输出: [1, 4, 9]16. filter:按条件筛选数组元素
遍历原数组,只把满足条件的元素放入一个新数组返回。// 老方法 (for 循环 + if + push)
const ages = [10, 20, 15, 30];
const adults = [];
for (let i = 0; i < ages.length; i++) {
if (ages[i] >= 18) {
adults.push(ages[i]);
}
}
// 新方法 (filter)
const ages = [10, 20, 15, 30];
const adults = ages.filter(age => age >= 18); // 只保留 >=18 的
console.log(adults); // 输出: [20, 30]17. reduce:把数组“压缩”成一个值
遍历数组,把元素逐个和一个“累加器”进行计算(比如累加、拼接、找最大值),最终得到一个结果值。功能很强大。// 老方法 (for 循环求和)
const prices = [10, 20, 5];
let totalPrice = 0;
for (let i = 0; i < prices.length; i++) {
totalPrice += prices[i];
}
// 新方法 (reduce 求和)
const prices = [10, 20, 5];
const totalPrice = prices.reduce((sum, price) => sum + price, 0); // 从0开始累加
console.log(totalPrice); // 输出: 35
// 复杂例子: 拍平数组 (把二维数组变一维)
const nestedArrays = [[1, 2], [3, 4], [5]];
const flattened = nestedArrays.reduce(
(acc, currentArray) => [...acc, ...currentArray], // 把当前数组展开拼接到累加器后面
[] // 初始累加器是空数组
);
console.log(flattened); // 输出: [1, 2, 3, 4, 5]18. Object.keys/values/entries:操作对象属性
方便地获取对象的键、值或者键值对数组,用来遍历对象。const car = {
make: "Toyota",
model: "Camry",
year: 2020
};
// 获取所有属性名 (keys)
console.log(Object.keys(car)); // 输出: ["make", "model", "year"]
// 获取所有属性值 (values)
console.log(Object.values(car)); // 输出: ["Toyota", "Camry", 2020]
// 获取键值对数组 (entries) - 每个元素是 [key, value]
console.log(Object.entries(car));
/* 输出:
[
["make", "Toyota"],
["model", "Camry"],
["year", 2020]
]
*/
// 用 entries 遍历对象
Object.entries(car).forEach(([key, value]) => {
console.log(`${key}: ${value}`);
});
/* 输出:
make: Toyota
model: Camry
year: 2020
*/19. 箭头函数隐式返回:省略 return
当箭头函数只有一行表达式时,可以省略 {} 和 return 关键字,直接写表达式,它会自动返回这个表达式的结果。// 显式返回
const add = (a, b) => {
return a + b;
};
// 隐式返回 (一行表达式)
const add = (a, b) => a + b; // 自动返回 a + b 的结果
console.log(add(5, 3)); // 输出: 8
// 隐式返回对象 (必须加括号)
const createUser = (name, age) => ({ name, age }); // 返回 {name: name, age: age}
console.log(createUser("Dora", 28)); // 输出: { name: 'Dora', age: 28 }20. !! 转布尔值:快速判断真假
用两个感叹号 !! 可以把任何类型的值快速转换成真正的布尔值 (true 或 false)。第一个 ! 把值转成布尔值再取反,第二个 ! 再取反一次,就得到原值的真实布尔等价。// 老方法 (if 判断赋值)
const value = "hello";
let isTruthy;
if (value) {
isTruthy = true;
} else {
isTruthy = false;
}
// 新方法 (!! 转换)
const value1 = "hello";
const isTruthy1 = !!value1; // !!'hello' -> true
console.log(isTruthy1); // 输出: true
const value2 = 0;
const isTruthy2 = !!value2; // !!0 -> false
console.log(isTruthy2); // 输出: false
const value3 = null;
const isTruthy3 = !!value3; // !!null -> false
console.log(isTruthy3); // 输出: false21. + 转数字:字符串变数字最快方法
在表示数字的字符串前面加一个 + 号,能快速把它转换成真正的数字类型。// 老方法 (parseInt/parseFloat)
const numStr = "123";
const num = parseInt(numStr, 10);
// 新方法 (+ 转换)
const numStr = "123";
const num = +numStr; // 字符串转整数
console.log(num, typeof num); // 输出: 123 'number'
const floatStr = "123.45";
const floatNum = +floatStr; // 字符串转浮点数
console.log(floatNum, typeof floatNum); // 输出: 123.45 'number'22. 属性简写:变量名即属性名
当对象的属性名和要赋值的变量名完全一样时,可以只写变量名,省略冒号和值。// 老方法
const firstName = "John";
const lastName = "Doe";
const age = 40;
const user = {
firstName: firstName, // 属性名: 变量名
lastName: lastName,
age: age
};
// 新方法 (属性简写)
const firstName = "John";
const lastName = "Doe";
const age = 40;
const user = {
firstName, // 等同于 firstName: firstName
lastName, // 等同于 lastName: lastName
age // 等同于 age: age
};
console.log(user); // 输出: { firstName: 'John', lastName: 'Doe', age: 40 }23. for...of 循环:直接遍历值
直接遍历数组、字符串等可迭代对象里的值,不需要操作索引 i。// 老方法 (for 循环遍历值)
const fruits = ["apple", "banana", "orange"];
for (let i = 0; i < fruits.length; i++) {
console.log(fruits[i]);
}
// 新方法 (for...of)
const fruits = ["apple", "banana", "orange"];
for (const fruit of fruits) { // fruit 直接是数组元素
console.log(fruit);
}
/*
输出:
apple
banana
orange
*/
// 遍历字符串
for (const char of "hello") {
console.log(char);
}
/*
输出:
h
e
l
l
o
*/24. 交换变量:不用临时变量
用数组解构,一行代码直接交换两个变量的值。// 老方法 (需要 temp 变量)
let a = 1;
let b = 2;
let temp = a;
a = b;
b = temp;
// 新方法 (解构交换)
let a = 1;
let b = 2;
[a, b] = [b, a]; // 右边创建 [2, 1], 左边解构赋值给 a, b
console.log(a, b); // 输出: 2 125. console.table():表格打印数据
调试神器!把对象数组或者对象本身在浏览器控制台里用清晰的表格打印出来,一目了然。const users = [
{ id: 1, name: "Alice", age: 28 },
{ id: 2, name: "Bob", age: 35 },
{ id: 3, name: "Charlie", age: 22 }
];
console.table(users);
/* 浏览器控制台输出类似表格:
(index) | id | name | age
--------|----|---------|----
0 | 1 | "Alice" | 28
1 | 2 | "Bob" | 35
2 | 3 | "Charlie"| 22
*/
const person = {
firstName: "Jane",
lastName: "Doe",
occupation: "Developer"
};
console.table(person);
/* 浏览器控制台输出类似表格:
(index) | Value
-----------|-----------
firstName | "Jane"
lastName | "Doe"
occupation | "Developer"
*/写在最后
这 25 个 JavaScript 技巧,都是现代开发中天天能用上的好东西。学会它们,能实实在在地帮你省下敲代码的时间,让代码看起来更整洁,写起来也更顺手。它们代表了 JavaScript 高效编程的核心方法。
别光看,赶紧在你下一个项目里试试这些技巧!用得越多,它们就越自然地成为你的编程习惯。坚持下去,你很快就能写出更专业、更漂亮的 JavaScript 代码了。收藏这篇文章,随时翻看备查吧!
本文内容仅供个人学习/研究/参考使用,不构成任何决策建议或专业指导。分享/转载时请标明原文来源,同时请勿将内容用于商业售卖、虚假宣传等非学习用途哦~感谢您的理解与支持!