你是不是也有过类似的经历?
- 后端返回的数据看起来正常,但JS就是解析不了
- 日期显示成一串看不懂的数字,还得手动转换
- 处理复杂数据时写了无数循环,代码又长又难维护
- 本地存储数据后再读取,发现格式全乱了
别担心,今天我就带你彻底掌握JSON和JS内置对象的使用技巧。学完这篇文章,你不仅能轻松解决这些问题,还能写出更优雅、更专业的数据处理代码!
JSON:数据交换的"普通话"
想象一下,你要跟一个外国朋友交流,但他说法语,你说中文,完全没法沟通怎么办?这时候就需要一种"通用语言"。
在编程世界里,JSON就是这种"通用语言"。它让前端、后端、移动端都能顺畅地"对话"。
JSON基础:比你想的还要简单
JSON说白了就是一种特殊格式的字符串,但它的规则超级严格:
javascript
// 正确的JSON格式
{
"name": "张三",
"age": 25,
"isStudent": false,
"hobbies": ["篮球", "编程", "音乐"],
"address": {
"city": "北京",
"district": "海淀区"
}
}
// 常见的错误写法
{
name: "张三", // 错误:属性名必须用双引号
'age': 25, // 错误:必须用双引号,不能用单引号
isStudent: false, // 错误:属性名没加引号
hobbies: ["篮球", "编程", "音乐"] // 错误:属性名没加引号
}
看到区别了吗?JSON的规则就是这么"死板",但正是这种严格保证了数据的一致性。
JSON的实战用法:不只是stringify和parse
你以为JSON就两个方法?那可就太小看它了!
javascript
// 场景1:深拷贝对象的完美方案
const originalObj = {
name: "李四",
scores: [90, 85, 95],
profile: {
height: 180,
weight: 70
}
};
// 常用的浅拷贝有问题
const shallowCopy = {...originalObj};
shallowCopy.profile.height = 190; // 这会修改原对象!
// 用JSON实现深拷贝
const deepCopy = JSON.parse(JSON.stringify(originalObj));
deepCopy.profile.height = 190; // 原对象不受影响
console.log(originalObj.profile.height); // 还是180,完美!
// 场景2:数据验证 - 确保拿到的是有效JSON
function safeParse(jsonString) {
try {
return JSON.parse(jsonString);
} catch (error) {
console.log('JSON格式错误,返回默认值');
return {};
}
}
// 这样就不怕后端返回异常数据了
const badData = "{name: '王五'}"; // 缺少引号的错误JSON
const goodData = safeParse(badData); // 不会报错,返回空对象
// 场景3:格式化显示,调试更轻松
const complexData = {
users: [
{id: 1, name: "用户1", permissions: ["read", "write"]},
{id: 2, name: "用户2", permissions: ["read"]}
]
};
// 第三个参数是缩进空格数,让输出更美观
console.log(JSON.stringify(complexData, null, 2));
内置对象:JS自带的"瑞士军刀"
如果说JSON是数据交换的工具,那内置对象就是数据处理的多功能工具箱。每个都有独特的本领,用对了能让你的代码效率翻倍!
Date对象:告别时间处理的头疼
时间处理是前端最常见的需求,也是最容易出bug的地方。
javascript
// 创建日期对象的多种方式
const now = new Date(); // 当前时间
const specificDate = new Date('2024-03-20'); // 特定日期
const timestamp = new Date(1647763200000); // 通过时间戳
// 实战:格式化日期显示
function formatDate(date) {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份从0开始,要+1
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
// 用法示例
const today = new Date();
console.log(formatDate(today)); // "2024-03-20"
// 更实用的:相对时间显示
function getRelativeTime(time) {
const now = new Date();
const diffInMs = now - time;
const diffInMinutes = Math.floor(diffInMs / (1000 * 60));
const diffInHours = Math.floor(diffInMs / (1000 * 60 * 60));
const diffInDays = Math.floor(diffInMs / (1000 * 60 * 60 * 24));
if (diffInMinutes < 1) return '刚刚';
if (diffInMinutes < 60) return `${diffInMinutes}分钟前`;
if (diffInHours < 24) return `${diffInHours}小时前`;
if (diffInDays < 7) return `${diffInDays}天前`;
return formatDate(time);
}
// 测试相对时间
const testTime = new Date(Date.now() - 2 * 60 * 60 * 1000); // 2小时前
console.log(getRelativeTime(testTime)); // "2小时前"
Math对象:数学计算不用愁
Math对象提供了一整套数学工具,很多开发者却只用了Math.random()。
javascript
// 实用技巧1:生成指定范围的随机数
function getRandomInRange(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
// 生成6位数字验证码
const verificationCode = getRandomInRange(100000, 999999);
console.log(verificationCode); // 比如:384756
// 实用技巧2:数值限制在范围内
function clamp(value, min, max) {
return Math.min(Math.max(value, min), max);
}
// 页面滚动进度计算
const scrollProgress = clamp(window.scrollY / document.body.scrollHeight, 0, 1);
console.log(scrollProgress); // 永远在0-1之间
// 实用技巧3:小数精度处理
const price = 19.899999;
console.log(price.toFixed(2)); // "19.90" - 自动四舍五入
// 但toFixed返回的是字符串,需要转数字
const cleanPrice = Number(price.toFixed(2));
console.log(cleanPrice); // 19.9
String对象:文本处理的艺术
字符串处理是日常开发的重头戏,掌握这些技巧能省下大量时间。
javascript
// 现代JS字符串处理技巧
const text = " Hello, JavaScript世界! ";
// 1. 去除空格的新方法
console.log(text.trim()); // "Hello, JavaScript世界!"
// 2. 检查字符串包含关系
console.log(text.includes("JavaScript")); // true
console.log(text.startsWith(" Hello")); // true
console.log(text.endsWith("世界! ")); // true
// 3. 字符串填充,适合显示对齐
const number = "25";
console.log(number.padStart(4, "0")); // "0025"
console.log(number.padEnd(4, "0")); // "2500"
// 实战:关键词高亮函数
function highlightKeywords(text, keywords) {
let result = text;
keywords.forEach(keyword => {
const regex = new RegExp(`(${keyword})`, 'gi');
result = result.replace(regex, '<mark>$1</mark>');
});
return result;
}
// 使用示例
const article = "JavaScript是一种强大的编程语言,学习JavaScript很有趣";
const highlighted = highlightKeywords(article, ["JavaScript", "编程"]);
console.log(highlighted);
// "<mark>JavaScript</mark>是一种强大的<mark>编程</mark>语言,学习<mark>JavaScript</mark>很有趣"
实战案例:构建一个完整的数据处理工具
光说不练假把式,我们来写一个真实可用的数据处理工具。
javascript
class DataProcessor {
constructor() {
this.cache = new Map(); // 用Map做缓存,比普通对象更合适
}
// 处理API返回的数据
processApiResponse(apiData) {
try {
// 1. 深拷贝原始数据
const data = JSON.parse(JSON.stringify(apiData));
// 2. 处理日期字段
if (data.createTime) {
data.createTime = new Date(data.createTime);
data.formattedTime = this.formatDate(data.createTime);
}
// 3. 处理数字字段
if (data.price) {
data.formattedPrice = `¥${Number(data.price).toFixed(2)}`;
}
// 4. 缓存处理结果
this.cache.set(apiData.id, data);
return data;
} catch (error) {
console.error('数据处理失败:', error);
return null;
}
}
// 格式化日期
formatDate(date) {
const now = new Date();
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
const targetDate = new Date(date.getFullYear(), date.getMonth(), date.getDate());
const diffTime = targetDate - today;
const diffDays = Math.floor(diffTime / (1000 * 60 * 60 * 24));
if (diffDays === 0) return '今天';
if (diffDays === 1) return '明天';
if (diffDays === -1) return '昨天';
return `${date.getMonth() + 1}月${date.getDate()}日`;
}
// 生成唯一ID
generateId(prefix = 'item') {
const timestamp = Date.now().toString(36);
const randomStr = Math.random().toString(36).substr(2, 5);
return `${prefix}_${timestamp}_${randomStr}`;
}
}
// 使用示例
const processor = new DataProcessor();
// 模拟API数据
const mockApiData = {
id: 1,
title: "JavaScript高级程序设计",
price: 89.9,
createTime: "2024-03-19T10:30:00Z",
tags: ["编程", "前端", "JavaScript"]
};
const processedData = processor.processApiResponse(mockApiData);
console.log(processedData);
// 输出:
// {
// id: 1,
// title: "JavaScript高级程序设计",
// price: 89.9,
// createTime: Date对象,
// formattedTime: "昨天",
// formattedPrice: "¥89.90",
// tags: ["编程", "前端", "JavaScript"]
// }
避坑指南:这些错误千万别犯!
在实际项目中,我见过太多因为不了解细节而导致的bug:
javascript
// 坑1:JSON不能处理undefined和函数
const problemObj = {
name: "测试",
method: function() { console.log('hello'); }, // 函数会被忽略
undefinedField: undefined // undefined会被忽略
};
console.log(JSON.stringify(problemObj));
// 输出:{"name":"测试"} - 函数和undefined都没了!
// 坑2:日期对象序列化会变成字符串
const dateObj = { createTime: new Date() };
const serialized = JSON.stringify(dateObj);
console.log(serialized); // {"createTime":"2024-03-20T03:45:30.123Z"}
const parsed = JSON.parse(serialized);
console.log(parsed.createTime instanceof Date); // false!变成了字符串
// 解决方案:使用reviver函数
const fixedParse = JSON.parse(serialized, (key, value) => {
if (typeof value === 'string' &&
/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3}Z$/.test(value)) {
return new Date(value);
}
return value;
});
console.log(fixedParse.createTime instanceof Date); // true!
// 坑3:数字精度问题
console.log(0.1 + 0.2 === 0.3); // false!
console.log(0.1 + 0.2); // 0.30000000000000004
// 解决方案:使用toFixed或者乘以10的倍数
function safeAdd(num1, num2) {
const multiplier = Math.pow(10, 10); // 根据精度需求调整
return (num1 * multiplier + num2 * multiplier) / multiplier;
}
console.log(safeAdd(0.1, 0.2) === 0.3); // true!
进阶技巧:让代码更优雅的秘诀
当你掌握了基础之后,来看看这些让代码更专业的技巧:
javascript
// 技巧1:使用Object.entries和Object.fromEntries
const user = {
name: "张三",
age: 25,
city: "北京"
};
// 过滤出年龄大于20的属性
const filtered = Object.fromEntries(
Object.entries(user).filter(([key, value]) => {
if (key === 'age') return value > 20;
return true;
})
);
console.log(filtered); // {name: "张三", age: 25, city: "北京"}
// 技巧2:使用Map代替对象作为字典
// 普通对象的键只能是字符串,Map可以是任意类型
const complexKey = { id: 1 };
const myMap = new Map();
myMap.set(complexKey, "对应的值");
console.log(myMap.get(complexKey)); // "对应的值"
// 技巧3:使用Set数组去重
const duplicateArray = [1, 2, 2, 3, 4, 4, 5];
const uniqueArray = [...new Set(duplicateArray)];
console.log(uniqueArray); // [1, 2, 3, 4, 5]
总结与思考
今天我们一起深入探索了JSON和JS内置对象的强大能力。从基础用法到实战技巧,从常见坑点到进阶方法,希望这些内容能真正帮到你。