当前位置: 首页 > news >正文

JavaScript ES6+ 最佳实践

1. 变量声明:从 varlet/const

问题代码var 存在变量提升,只有函数作用域,没有块级作用域,容易导致变量污染。

// 变量提升导致意外行为
console.log(num); // undefined 而非报错
var num = 10;
// 没有块级作用域
var name = '张三';
if (true) {var name = '李四'; // 覆盖外部作用域的name
}
console.log(name); // 输出 '李四'for (var i = 0; i < 5; i++) {setTimeout(function() {console.log(i); // 输出5个5}, 100);
}

ES6+ 解决方案

const name = '张三'; // 不可重新赋值的常量
if (true) {let name = '李四'; // 块级作用域
}
console.log(name); // '张三'for (let i = 0; i < 5; i++) {setTimeout(() => console.log(i), 100); // 0,1,2,3,4
}

最佳实践

  • 默认使用 const
  • 需要重新赋值时使用 let
  • 避免使用 var
2. 函数定义:从函数表达式到箭头函数

问题代码:冗长的语法,this 绑定问题。

var add = function(a, b) {return a + b;
};var obj = {value: 1,increment: function() {var self = this;setTimeout(function() {self.value++;}, 100);}
};

ES6+ 解决方案

const add = (a, b) => a + b;const obj = {value: 1,increment() {setTimeout(() => {this.value++;}, 100);}
};

特性

  • 箭头函数继承外层 this
  • 方法简写语法
  • 隐式返回
3. 异步编程:从回调地狱到 Promise/async-await

问题代码

getData(function(a) {getMoreData(a, function(b) {getEvenMoreData(b, function(c) {getFinalData(c, function(result) {console.log('Result:', result);}, failCallback);}, failCallback);}, failCallback);
}, failCallback);

ES6+ 解决方案

// Promise 链
getData().then(a => getMoreData(a)).then(b => getEvenMoreData(b)).then(c => getFinalData(c)).then(result => console.log('Result:', result)).catch(error => console.error(error));// async、await
async function processData() {try {const a = await getData();const b = await getMoreData(a);const c = await getEvenMoreData(b);const result = await getFinalData(c);console.log('Result:', result);} catch (error) {console.error(error);}
}

优势

  • 线性代码结构
  • 统一错误处理
  • 更好的可读性
4. 参数处理:从 arguments 到剩余参数

问题代码

function sum() {var args = Array.prototype.slice.call(arguments);return args.reduce(function(total, num) {return total + num;}, 0);
}

ES6+ 解决方案

function sum(...numbers) {return numbers.reduce((total, num) => total + num, 0);
}

特点

  • 真正的数组
  • 更清晰的参数定义
  • 可与普通参数混用
5. 面向对象:从构造函数到类语法

问题代码

function Person(name) {this.name = name;
}
Person.prototype.sayHello = function() {console.log('Hello, ' + this.name);
};

ES6+ 解决方案

class Person {constructor(name) {this.name = name;}sayHello() {console.log(`Hello, ${this.name}`);}// 静态方法static create(name) {return new Person(name);}
}

新增特性

  • 继承 (extends)
  • 静态方法
  • 私有字段 (#field)
  • 静态块
6. 字符串处理:从拼接符到模板字符串

问题代码

var name = '张三';
var age = 25;
var message = name + '今年' + age + '岁';

ES6+ 解决方案

const message = `${name}今年${age}`;

高级用法

// 多行字符串
const html = `
<div><h1>${title}</h1><p>${content}</p>
</div>
`;// 标签模板
function highlight(strings, ...values) {return strings.reduce((result, str, i) => `${result}${str}<span class="highlight">${values[i] || ''}</span>`, '');
}
const output = highlight`Hello ${name}, welcome to ${siteName}!`;
7. 对象和数组处理:从手动操作到展开运算符

问题代码

var arr1 = [1, 2, 3];
var arr2 = [4, 5, 6];
var combined = arr1.concat(arr2);var obj1 = { a: 1, b: 2 };
var obj2 = { b: 3, c: 4 };
var merged = Object.assign({}, obj1, obj2);

ES6+ 解决方案

const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2];const obj1 = { a: 1, b: 2 };
const obj2 = { b: 3, c: 4 };
const merged = { ...obj1, ...obj2 };

实用技巧

// 数组复制
const copy = [...original];// 对象属性覆盖
const defaults = { color: 'red', size: 'medium' };
const config = { ...defaults, ...userConfig };// 剩余参数解构
const { a, b, ...rest } = { a: 1, b: 2, c: 3, d: 4 };
8. 数组迭代:从 for 循环到高阶函数

问题代码

var numbers = [1, 2, 3, 4];
var doubled = [];
for (var i = 0; i < numbers.length; i++) {doubled.push(numbers[i] * 2);
}

ES6+ 解决方案

const numbers = [1, 2, 3, 4];
const doubled = numbers.map(num => num * 2);

常用高阶函数

// 过滤
const evens = numbers.filter(n => n % 2 === 0);// 累加
const sum = numbers.reduce((total, num) => total + num, 0);// 查找
const firstEven = numbers.find(n => n % 2 === 0);// 检查
const allPositive = numbers.every(n => n > 0);
const hasNegative = numbers.some(n => n < 0);
9. 模块系统:从 IIFE 到 ES Modules

问题代码

// math.js
(function() {function add(a, b) { return a + b; }function subtract(a, b) { return a - b; }window.math = { add: add, subtract: subtract };
})();// app.js
math.add(1, 2);

ES6+ 解决方案

// math.js
export function add(a, b) { return a + b; }
export function subtract(a, b) { return a - b; }// app.js
import { add } from './math.js';
add(1, 2);

现代模块特性

  • 命名导出/默认导出
  • 动态导入 (import())
  • 顶层 await
  • 模块元信息 (import.meta)
10. 其他重要 ES6+ 特性

解构赋值

// 对象解构
const { name, age } = person;
const { name: personName, age: personAge } = person;// 数组解构
const [first, second] = numbers;
const [head, ...tail] = numbers;

可选链 (?.) 和空值合并 (??)

// 避免 Cannot read property 'x' of undefined/null
const street = user?.address?.street ?? 'Unknown';// 函数调用可选链
someInterface.customMethod?.();

BigInt

const bigNumber = 9007199254740991n;
const biggerNumber = bigNumber + 1n;

全局对象标准化

// 浏览器环境
globalThis === window; // true// Node.js 环境
globalThis === global; // true
11.类型系统缺陷

原始问题

// 1. typeof null === 'object'
typeof null; // "object" (从JS诞生就存在的bug)// 2. 隐式类型转换
[] + {}; // "[object Object]"
{} + []; // 0// 3. == 的强制类型转换
'0' == false; // true

现代化实践

// 1. 使用 Object.prototype.toString 检测类型
Object.prototype.toString.call(null); // "[object Null]"// 2. 避免隐式转换,使用显式转换
Number([]) + Number({}); // NaN// 3. 始终使用 ===
'0' === false; // false

相关文章:

  • 【DB2】DB2启动失败报错SQL1042C
  • 2025-05-07 Unity 网络基础7——TCP异步通信
  • 什么是声明式UI什么是命令式UI?鸿蒙ArkTS为什么是声明式UI-优雅草卓伊凡
  • 智算中心基础设施0-1建设全流程及投产后的运维
  • 融合静态图与动态智能:重构下一代智能系统架构
  • CPU-GPU-NPU-TPU 概念
  • 【HarmonyOS 5】鸿蒙Web组件和内嵌网页双向通信DEMO示例
  • Feign 重试策略调整:优化微服务通信的稳定性
  • PAT(最近)
  • 商汤科技前端面试题及参考答案
  • 如何避免项目结束后知识流失
  • 【基础知识】常见公式计算(三)
  • 【论文阅读】Harnessing the Power of LLM to Support Binary Taint Analysis
  • 汽车服务小程序功能点开发
  • 密码学基石:哈希、对称/非对称加密与HTTPS实践详解
  • 世界无人机大会将至,大势智慧以“AI+实景三维”赋能低空经济
  • TypeScript类型挑战-刷题
  • 适合java程序员的Kafka消息中间件实战
  • Kafka生产者send方法详解
  • phpstudy升级新版apache
  • 提供做网站/百度推广有哪些推广方式
  • 建一个网站的费用/西地那非片能延时多久
  • 武汉做网站熊掌号/长沙优化科技有限公司正规吗
  • 营销型网站制作平台/重庆seo全面优化
  • 无锡地区做网站/百度指数在线查询工具
  • 网站建设企业电话/免费的短视频app大全