告别数据混乱!掌握JSON与内置对象,让你的JS代码更专业

你是不是也有过类似的经历?

  • 后端返回的数据看起来正常,但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内置对象的强大能力。从基础用法到实战技巧,从常见坑点到进阶方法,希望这些内容能真正帮到你。

相关推荐
liangshanbo12159 小时前
写好 React useEffect 的终极指南
前端·javascript·react.js
哆啦A梦158811 小时前
搜索页面布局
前端·vue.js·node.js
_院长大人_12 小时前
el-table-column show-overflow-tooltip 只能显示纯文本,无法渲染 <p> 标签
前端·javascript·vue.js
SevgiliD12 小时前
el-table中控制单列内容多行超出省略及tooltip
javascript·vue.js·elementui
要加油哦~12 小时前
JS | 知识点总结 - 原型链
开发语言·javascript·原型模式
哆啦A梦158813 小时前
axios 的二次封装
前端·vue.js·node.js
阿珊和她的猫13 小时前
深入理解与手写发布订阅模式
开发语言·前端·javascript·vue.js·ecmascript·状态模式
yinuo13 小时前
一行 CSS 就能搞定!用 writing-mode 轻松实现文字竖排
前端