欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JSON.stringify 基礎(chǔ)與進(jìn)階用法完全攻略

 更新時(shí)間:2025年09月16日 09:27:35   作者:珍寶商店  
掌握J(rèn)SON.stringify核心功能,包括數(shù)據(jù)類型支持、嵌套處理、循環(huán)引用檢測(cè)、格式化輸出及安全性保障,適用于API傳輸、配置生成等場(chǎng)景,助開發(fā)者高效處理數(shù)據(jù),本文給大家介紹JSON.stringify基礎(chǔ)與進(jìn)階用法完全攻略,感興趣的朋友跟隨小編一起看看吧

JSON.stringify 基礎(chǔ)與進(jìn)階用法指南

關(guān)鍵特性概覽

?? 核心能力

JSON.stringify 是 JavaScript 內(nèi)置的序列化方法,具有以下關(guān)鍵特性:

1.通用序列化支持
  • ? 支持所有 JSON 兼容的數(shù)據(jù)類型
  • ? 自動(dòng)處理嵌套對(duì)象和數(shù)組
  • ? 保持?jǐn)?shù)據(jù)結(jié)構(gòu)的完整性
  • ? 自動(dòng)忽略 undefined、Symbol 和函數(shù)類型的屬性
  • ? 只序列化對(duì)象自身的可枚舉屬性
  • ? 日期對(duì)象還沒轉(zhuǎn)化為 ISO 格式字符串
  • ? 循環(huán)引用會(huì)拋出錯(cuò)誤
// 支持復(fù)雜數(shù)據(jù)結(jié)構(gòu)
const complexData = {
  users: [
    { id: 1, name: '張三', active: true },
    { id: 2, name: '李四', active: false },
  ],
  metadata: {
    total: 2,
    timestamp: '2025-09-15T10:30:00.000Z',
  },
};
// 一鍵序列化
JSON.stringify(complexData);
2.靈活的數(shù)據(jù)轉(zhuǎn)換
  • ?? Replacer 函數(shù)自定義轉(zhuǎn)換邏輯
  • ?? 白名單模式精確控制輸出
  • ?? toJSON 方法實(shí)現(xiàn)對(duì)象級(jí)別控制
// 多種轉(zhuǎn)換方式
const data = { name: '測(cè)試', password: 'secret', age: 25 };
// 方式1:函數(shù)過濾
JSON.stringify(data, (k, v) => (k === 'password' ? undefined : v));
// 方式2:白名單模式
JSON.stringify(data, ['name', 'age']);
// 方式3:對(duì)象自定義
data.toJSON = () => ({ name: data.name, age: data.age });
3.智能格式化輸出
  • ?? 支持縮進(jìn)美化
  • ?? 自定義縮進(jìn)字符
  • ?? 壓縮與可讀性平衡
const obj = { a: 1, b: { c: 2 } };
// 壓縮輸出
JSON.stringify(obj); // {"a":1,"b":{"c":2}}
// 美化輸出
JSON.stringify(obj, null, 2);
/*
{
  "a": 1,
  "b": {
    "c": 2
  }
}
*/
// 自定義縮進(jìn)
JSON.stringify(obj, null, '→');
/*
{
→"a": 1,
→"b": {
→→"c": 2
→}
}
*/
4.安全性保障
  • ??? 自動(dòng)過濾不安全的數(shù)據(jù)類型
  • ??? 防止代碼注入
  • ??? 循環(huán)引用檢測(cè)(需自定義處理)
const unsafeData = {
  name: '用戶',
  method: function () {
    return 'danger';
  }, // 被忽略
  symbol: Symbol('test'), // 被忽略
  undef: undefined, // 被忽略
  safe: 'normal string', // 保留
};
JSON.stringify(unsafeData);
// 輸出: {"name":"用戶","safe":"normal string"}

?? 核心優(yōu)勢(shì)

特性描述應(yīng)用場(chǎng)景
原生支持瀏覽器和 Node.js 內(nèi)置無需額外依賴
高性能C++ 底層實(shí)現(xiàn),速度快大數(shù)據(jù)序列化
標(biāo)準(zhǔn)兼容嚴(yán)格遵循 JSON 規(guī)范跨平臺(tái)數(shù)據(jù)交換
靈活配置多參數(shù)精確控制復(fù)雜業(yè)務(wù)需求
錯(cuò)誤處理明確的異常機(jī)制生產(chǎn)環(huán)境穩(wěn)定性

? 性能特點(diǎn)

// 性能基準(zhǔn)測(cè)試示例
function benchmarkStringify() {
  const testData = new Array(10000).fill(0).map((_, i) => ({
    id: i,
    name: `用戶${i}`,
    score: Math.random() * 100,
    active: i % 2 === 0,
  }));
  console.time('JSON.stringify');
  const result = JSON.stringify(testData);
  console.timeEnd('JSON.stringify');
  console.log(`數(shù)據(jù)大小: ${result.length} 字符`);
  console.log(
    `壓縮率: ${(
      (result.length / JSON.stringify(testData, null, 2).length) *
      100
    ).toFixed(1)}%`
  );
}
benchmarkStringify();
// 典型輸出:
// JSON.stringify: 15.234ms
// 數(shù)據(jù)大小: 889123 字符
// 壓縮率: 45.2%

?? 兼容性矩陣

環(huán)境版本支持特性完整度備注
Chrome4+100%完全支持
Firefox3.5+100%完全支持
Safari4+100%完全支持
IE8+100%原生支持
Node.js0.1+100%服務(wù)端支持
React Native全版本100%移動(dòng)端支持

??? 擴(kuò)展能力

// 擴(kuò)展 JSON.stringify 功能示例
class EnhancedJSON {
  static stringify(obj, options = {}) {
    const {
      // 基礎(chǔ)選項(xiàng)
      replacer = null,
      space = null,
      // 擴(kuò)展選項(xiàng)
      maxDepth = Infinity,
      dateFormat = 'iso', // 'iso' | 'timestamp' | 'locale'
      errorHandler = 'throw', // 'throw' | 'skip' | 'placeholder'
      bigintSupport = false, // 是否支持 BigInt
      functionSupport = false, // 是否保留函數(shù)
      // 安全選項(xiàng)
      sensitiveKeys = ['password', 'token', 'secret'],
      maxSize = 1024 * 1024, // 最大 1MB
      // 性能選項(xiàng)
      cache = false, // 是否啟用緩存
      stream = false, // 是否流式處理
    } = options;
    // 實(shí)現(xiàn)增強(qiáng)的序列化邏輯...
    return this._enhancedStringify(obj, {
      replacer,
      space,
      maxDepth,
      dateFormat,
      errorHandler,
      bigintSupport,
      functionSupport,
      sensitiveKeys,
      maxSize,
      cache,
      stream,
    });
  }
  static _enhancedStringify(obj, options) {
    // 詳細(xì)實(shí)現(xiàn)邏輯...
    // 這里可以添加各種增強(qiáng)功能
  }
}

基礎(chǔ)語法

JSON.stringify(value[, replacer[, space]])

參數(shù)說明:

  • value: 要序列化的值
  • replacer (可選): 轉(zhuǎn)換器函數(shù)或數(shù)組,用于過濾和轉(zhuǎn)換結(jié)果
  • space (可選): 用于美化輸出的空白字符

基礎(chǔ)用法

1. 簡(jiǎn)單對(duì)象序列化

const obj = {
  name: '張三',
  age: 25,
  city: '北京',
};
console.log(JSON.stringify(obj));
// 輸出: {"name":"張三","age":25,"city":"北京"}

2. 數(shù)組序列化

const arr = [1, 2, 3, 'hello', true];
console.log(JSON.stringify(arr));
// 輸出: [1,2,3,"hello",true]

3. 嵌套對(duì)象序列化

const complexObj = {
  user: {
    name: '李四',
    profile: {
      age: 30,
      hobbies: ['讀書', '游泳', '編程'],
    },
  },
  timestamp: new Date(),
};
console.log(JSON.stringify(complexObj));
// 輸出: {"user":{"name":"李四","profile":{"age":30,"hobbies":["讀書","游泳","編程"]}},"timestamp":"2025-09-15T10:30:00.000Z"}

進(jìn)階用法

1. toJSON 方法

對(duì)象可以定義 toJSON 方法來自定義序列化行為:

class User {
  constructor(name, password, email) {
    this.name = name;
    this.password = password;
    this.email = email;
  }
  toJSON() {
    // 排除敏感信息
    return {
      name: this.name,
      email: this.email,
    };
  }
}
const user = new User('王五', 'secret123', 'wangwu@example.com');
console.log(JSON.stringify(user));
// 輸出: {"name":"王五","email":"wangwu@example.com"}

2. Date 對(duì)象的處理

const dateObj = {
  created: new Date(),
  updated: new Date('2024-01-01'),
};
console.log(JSON.stringify(dateObj));
// 輸出: {"created":"2025-09-15T10:30:00.000Z","updated":"2024-01-01T00:00:00.000Z"}
// 自定義 Date 序列化
Date.prototype.toJSON = function () {
  return this.getTime(); // 返回時(shí)間戳
};
console.log(JSON.stringify(dateObj));
// 輸出: {"created":1726397400000,"updated":1704067200000}

選擇性序列化

選擇性序列化是 JSON.stringify 最強(qiáng)大的功能之一,允許我們精確控制哪些數(shù)據(jù)被序列化,如何轉(zhuǎn)換數(shù)據(jù),以及輸出格式。

?? 核心概念

選擇性序列化主要通過以下三種方式實(shí)現(xiàn):

  1. Replacer 函數(shù) - 逐個(gè)處理每個(gè)鍵值對(duì)
  2. Replacer 數(shù)組 - 白名單模式指定屬性
  3. toJSON 方法 - 對(duì)象級(jí)別的自定義序列化

1. 基于函數(shù)的選擇性序列化

1.1 基礎(chǔ)過濾
const userData = {
  id: 1001,
  username: 'zhangsan',
  password: 'secret123',
  email: 'zhangsan@example.com',
  phone: '13800138000',
  role: 'admin',
  lastLogin: new Date(),
  settings: {
    theme: 'dark',
    notifications: true,
    apiKey: 'sk-1234567890abcdef',
  },
};
// 基礎(chǔ)敏感信息過濾
const publicData = JSON.stringify(userData, (key, value) => {
  // 過濾敏感字段
  const sensitiveKeys = ['password', 'apiKey'];
  if (sensitiveKeys.includes(key)) {
    return undefined; // 完全移除
  }
  return value;
});
console.log(publicData);
// 輸出: {"id":1001,"username":"zhangsan","email":"zhangsan@example.com",...}
1.2 數(shù)據(jù)脫敏
const sensitiveData = {
  name: '張三',
  idCard: '110101199001011234',
  phone: '13800138000',
  email: 'zhangsan@example.com',
  bankCard: '6222021234567890123',
  salary: 15000,
};
// 數(shù)據(jù)脫敏處理
const maskedData = JSON.stringify(sensitiveData, (key, value) => {
  switch (key) {
    case 'idCard':
      // 身份證脫敏:顯示前6位和后4位
      return value.replace(/(\d{6})\d*(\d{4})/, '$1******$2');
    case 'phone':
      // 手機(jī)號(hào)脫敏:顯示前3位和后4位
      return value.replace(/(\d{3})\d*(\d{4})/, '$1****$2');
    case 'email':
      // 郵箱脫敏:用戶名部分脫敏
      return value.replace(/(.{2}).*(@.*)/, '$1***$2');
    case 'bankCard':
      // 銀行卡脫敏:只顯示后4位
      return '****' + value.slice(-4);
    case 'salary':
      // 薪資脫敏:轉(zhuǎn)為范圍
      const salaryRange = Math.floor(value / 5000) * 5000;
      return `${salaryRange}-${salaryRange + 4999}`;
    default:
      return value;
  }
});
console.log(JSON.parse(maskedData));
// 輸出: {
//   name: "張三",
//   idCard: "110101******1234",
//   phone: "138****8000",
//   email: "zh***@example.com",
//   bankCard: "****0123",
//   salary: "15000-19999"
// }
1.3 條件序列化
const productData = {
  id: 'p001',
  name: 'iPhone 15',
  price: 7999,
  cost: 4500, // 內(nèi)部成本,不對(duì)外
  inventory: 150,
  status: 'active',
  internal: {
    supplier: 'Apple Inc',
    margin: 43.7, // 利潤率,敏感信息
    notes: 'Q4 熱銷產(chǎn)品',
  },
  public: {
    description: '最新款智能手機(jī)',
    features: ['A17 芯片', '48MP 相機(jī)', '128GB 存儲(chǔ)'],
  },
};
// 根據(jù)用戶權(quán)限選擇性序列化
function createProductSerializer(userRole) {
  return (key, value) => {
    // 所有用戶都不能看到的字段
    if (['cost'].includes(key)) {
      return undefined;
    }
    // 只有管理員能看到的字段
    if (userRole !== 'admin') {
      if (['internal', 'margin'].includes(key)) {
        return undefined;
      }
    }
    // 特殊處理
    if (key === 'inventory' && userRole === 'customer') {
      // 客戶只能看到庫存狀態(tài),不能看到具體數(shù)量
      return value > 0 ? '有庫存' : '無庫存';
    }
    return value;
  };
}
// 管理員視圖
const adminView = JSON.stringify(
  productData,
  createProductSerializer('admin'),
  2
);
// 客戶視圖
const customerView = JSON.stringify(
  productData,
  createProductSerializer('customer'),
  2
);
console.log('管理員視圖:', adminView);
console.log('客戶視圖:', customerView);

2. 基于數(shù)組的選擇性序列化

2.1 白名單模式
const fullUserProfile = {
  // 基本信息
  id: 1001,
  username: 'zhangsan',
  email: 'zhangsan@example.com',
  // 敏感信息
  password: 'secret123',
  ssn: '123-45-6789',
  // 個(gè)人信息
  firstName: '三',
  lastName: '張',
  age: 28,
  // 系統(tǒng)信息
  createdAt: '2024-01-01T00:00:00.000Z',
  updatedAt: '2025-09-15T10:30:00.000Z',
  isActive: true,
  // 配置信息
  preferences: {
    language: 'zh-CN',
    timezone: 'Asia/Shanghai',
    theme: 'dark',
  },
};
// 定義不同場(chǎng)景的字段白名單
const whitelists = {
  // 公開資料
  public: ['id', 'username', 'firstName', 'lastName'],
  // 個(gè)人資料編輯
  profile: [
    'id',
    'username',
    'email',
    'firstName',
    'lastName',
    'age',
    'preferences',
  ],
  // 系統(tǒng)管理
  admin: ['id', 'username', 'email', 'isActive', 'createdAt', 'updatedAt'],
  // API 響應(yīng)
  api: ['id', 'username', 'email', 'firstName', 'lastName', 'isActive'],
};
// 使用不同白名單
Object.entries(whitelists).forEach(([scenario, fields]) => {
  const result = JSON.stringify(fullUserProfile, fields, 2);
  console.log(`${scenario} 場(chǎng)景:`, result);
});
2.2 動(dòng)態(tài)白名單
class FieldSelector {
  constructor() {
    this.baseFields = ['id', 'name', 'type'];
    this.conditionalFields = new Map();
  }
  // 添加條件字段
  addConditionalField(condition, fields) {
    this.conditionalFields.set(condition, fields);
    return this;
  }
  // 生成字段列表
  getFields(context = {}) {
    let fields = [...this.baseFields];
    for (const [condition, additionalFields] of this.conditionalFields) {
      if (typeof condition === 'function' && condition(context)) {
        fields.push(...additionalFields);
      } else if (typeof condition === 'string' && context[condition]) {
        fields.push(...additionalFields);
      }
    }
    return [...new Set(fields)]; // 去重
  }
}
const productSelector = new FieldSelector()
  .addConditionalField((ctx) => ctx.userRole === 'admin', ['cost', 'supplier'])
  .addConditionalField(
    (ctx) => ctx.showDetails,
    ['description', 'specifications']
  )
  .addConditionalField('includeStock', ['inventory', 'reserved']);
const product = {
  id: 'p001',
  name: 'MacBook Pro',
  type: 'laptop',
  price: 12999,
  cost: 8000,
  supplier: 'Apple',
  inventory: 50,
  reserved: 5,
  description: '專業(yè)級(jí)筆記本電腦',
  specifications: { cpu: 'M3', ram: '16GB', storage: '512GB' },
};
// 不同上下文的序列化
const contexts = [
  { userRole: 'customer', showDetails: false },
  { userRole: 'admin', showDetails: true, includeStock: true },
  { userRole: 'sales', showDetails: true },
];
contexts.forEach((context, index) => {
  const fields = productSelector.getFields(context);
  const result = JSON.stringify(product, fields, 2);
  console.log(`Context ${index + 1}:`, result);
});

3. 基于 toJSON 的選擇性序列化

3.1 智能對(duì)象序列化
class SmartUser {
  constructor(data) {
    Object.assign(this, data);
    this._sensitive = ['password', 'ssn', 'creditCard'];
    this._internal = ['_sensitive', '_internal', '_context'];
  }
  // 設(shè)置序列化上下文
  setContext(context) {
    this._context = context;
    return this;
  }
  toJSON() {
    const result = {};
    const context = this._context || {};
    for (const [key, value] of Object.entries(this)) {
      // 跳過內(nèi)部字段
      if (this._internal.includes(key)) continue;
      // 處理敏感字段
      if (this._sensitive.includes(key)) {
        if (context.includeSensitive) {
          result[key] = context.maskSensitive
            ? this._maskValue(key, value)
            : value;
        }
        continue;
      }
      // 處理嵌套對(duì)象
      if (value && typeof value === 'object' && value.toJSON) {
        result[key] = value.toJSON();
      } else {
        result[key] = value;
      }
    }
    return result;
  }
  _maskValue(key, value) {
    switch (key) {
      case 'password':
        return '***';
      case 'ssn':
        return value.replace(/\d/g, '*');
      case 'creditCard':
        return value.replace(/\d(?=\d{4})/g, '*');
      default:
        return value;
    }
  }
}
const user = new SmartUser({
  id: 1001,
  name: '張三',
  email: 'zhangsan@example.com',
  password: 'secret123',
  ssn: '123-45-6789',
  role: 'user',
});
// 不同上下文的序列化
console.log('默認(rèn)序列化:', JSON.stringify(user, null, 2));
console.log(
  '包含敏感信息:',
  JSON.stringify(user.setContext({ includeSensitive: true }), null, 2)
);
console.log(
  '脫敏序列化:',
  JSON.stringify(
    user.setContext({ includeSensitive: true, maskSensitive: true }),
    null,
    2
  )
);
3.2 多版本序列化
class VersionedData {
  constructor(data) {
    this.data = data;
    this.versions = new Map();
  }
  // 注冊(cè)版本序列化器
  registerVersion(version, serializer) {
    this.versions.set(version, serializer);
    return this;
  }
  // 設(shè)置當(dāng)前版本
  setVersion(version) {
    this.currentVersion = version;
    return this;
  }
  toJSON() {
    const version = this.currentVersion || 'default';
    const serializer = this.versions.get(version);
    if (serializer) {
      return serializer(this.data);
    }
    return this.data;
  }
}
const apiData = new VersionedData({
  id: 1001,
  username: 'zhangsan',
  email: 'zhangsan@example.com',
  profile: {
    firstName: '三',
    lastName: '張',
    age: 28,
    avatar: 'https://example.com/avatar.jpg',
  },
  settings: {
    theme: 'dark',
    language: 'zh-CN',
  },
  createdAt: new Date('2024-01-01'),
  updatedAt: new Date(),
});
// 注冊(cè)不同版本的序列化器
apiData
  .registerVersion('v1', (data) => ({
    id: data.id,
    name: data.username,
    email: data.email,
    created: data.createdAt.toISOString(),
  }))
  .registerVersion('v2', (data) => ({
    id: data.id,
    username: data.username,
    email: data.email,
    profile: {
      name: `${data.profile.lastName}${data.profile.firstName}`,
      age: data.profile.age,
      avatar: data.profile.avatar,
    },
    metadata: {
      created: data.createdAt.toISOString(),
      updated: data.updatedAt.toISOString(),
    },
  }))
  .registerVersion('v3', (data) => ({
    user: {
      id: data.id,
      username: data.username,
      email: data.email,
      profile: data.profile,
      preferences: data.settings,
    },
    timestamps: {
      createdAt: data.createdAt.getTime(),
      updatedAt: data.updatedAt.getTime(),
    },
  }));
// 使用不同版本
['v1', 'v2', 'v3'].forEach((version) => {
  console.log(
    `API ${version}:`,
    JSON.stringify(apiData.setVersion(version), null, 2)
  );
});

??? 實(shí)用工具類

// 選擇性序列化工具類
class SelectiveStringify {
  static create() {
    return new SelectiveStringify();
  }
  constructor() {
    this.rules = [];
    this.globalOptions = {};
  }
  // 添加字段規(guī)則
  field(fieldPath, rule) {
    this.rules.push({ path: fieldPath, rule });
    return this;
  }
  // 排除字段
  exclude(...fields) {
    fields.forEach((field) => this.field(field, () => undefined));
    return this;
  }
  // 包含字段
  include(...fields) {
    this.includeOnly = new Set(fields);
    return this;
  }
  // 脫敏字段
  mask(field, maskFn) {
    this.field(field, (value) => (maskFn ? maskFn(value) : '***'));
    return this;
  }
  // 轉(zhuǎn)換字段
  transform(field, transformFn) {
    this.field(field, transformFn);
    return this;
  }
  // 條件字段
  when(field, condition, thenRule, elseRule) {
    this.field(field, (value, context) => {
      const shouldApply =
        typeof condition === 'function'
          ? condition(value, context)
          : context[condition];
      return shouldApply
        ? typeof thenRule === 'function'
          ? thenRule(value, context)
          : thenRule
        : typeof elseRule === 'function'
        ? elseRule(value, context)
        : elseRule;
    });
    return this;
  }
  // 執(zhí)行序列化
  stringify(obj, context = {}, space = null) {
    const replacer = (key, value) => {
      if (key === '') return value;
      // 包含字段檢查
      if (this.includeOnly && !this.includeOnly.has(key)) {
        return undefined;
      }
      // 應(yīng)用字段規(guī)則
      for (const { path, rule } of this.rules) {
        if (this.matchPath(key, path)) {
          const result = rule(value, context);
          if (result !== value) return result;
        }
      }
      return value;
    };
    return JSON.stringify(obj, replacer, space);
  }
  matchPath(key, path) {
    if (typeof path === 'string') return key === path;
    if (path instanceof RegExp) return path.test(key);
    if (typeof path === 'function') return path(key);
    return false;
  }
}
// 使用示例
const data = {
  id: 1001,
  username: 'zhangsan',
  password: 'secret123',
  email: 'zhangsan@example.com',
  phone: '13800138000',
  profile: {
    age: 28,
    salary: 25000,
  },
  createdAt: new Date(),
  logs: ['login', 'update', 'logout'],
};
// 鏈?zhǔn)脚渲眯蛄谢?guī)則
const result = SelectiveStringify.create()
  .exclude('password')
  .mask('phone', (phone) => phone.replace(/(\d{3})\d{4}(\d{4})/, '$1****$2'))
  .transform('email', (email) => email.toLowerCase())
  .when(
    'salary',
    (value, ctx) => ctx.userRole === 'admin',
    (value) => value,
    () => '機(jī)密'
  )
  .transform('createdAt', (date) => date.toISOString())
  .stringify(data, { userRole: 'user' }, 2);
console.log(result);

Replacer 參數(shù)詳解

1. 函數(shù)形式的 Replacer

const data = {
  name: '測(cè)試',
  password: '123456',
  email: 'test@example.com',
  age: 25,
  salary: 50000,
};
// 過濾敏感信息
const safeStringify = JSON.stringify(data, (key, value) => {
  if (key === 'password') return undefined;
  if (key === 'salary') return '***';
  return value;
});
console.log(safeStringify);
// 輸出: {"name":"測(cè)試","email":"test@example.com","age":25,"salary":"***"}

2. 數(shù)組形式的 Replacer

const user = {
  id: 1,
  name: '張三',
  password: 'secret',
  email: 'zhangsan@example.com',
  phone: '13800138000',
  address: '北京市朝陽區(qū)',
};
// 只序列化指定的屬性
const publicInfo = JSON.stringify(user, ['id', 'name', 'email']);
console.log(publicInfo);
// 輸出: {"id":1,"name":"張三","email":"zhangsan@example.com"}

3. 高級(jí) Replacer 用法

const data = {
  users: [
    { name: '用戶1', score: 85.6789 },
    { name: '用戶2', score: 92.1234 },
  ],
  timestamp: Date.now(),
};
const customReplacer = (key, value) => {
  // 數(shù)字保留兩位小數(shù)
  if (typeof value === 'number' && key === 'score') {
    return Number(value.toFixed(2));
  }
  // 時(shí)間戳轉(zhuǎn)換為可讀格式
  if (key === 'timestamp') {
    return new Date(value).toISOString();
  }
  return value;
};
console.log(JSON.stringify(data, customReplacer, 2));

Space 參數(shù)詳解

Space 參數(shù)是 JSON.stringify 中控制輸出格式的關(guān)鍵參數(shù),合理使用可以大大提升開發(fā)效率和代碼可讀性。

?? 核心功能概述

Space 參數(shù)主要用于:

  • 調(diào)試輸出 - 讓 JSON 數(shù)據(jù)更易讀,便于調(diào)試
  • 文檔生成 - 創(chuàng)建格式化的示例數(shù)據(jù)
  • 配置文件 - 生成人類友好的配置文件
  • API 文檔 - 展示結(jié)構(gòu)化的響應(yīng)示例

1. 數(shù)字格式化 - 標(biāo)準(zhǔn)縮進(jìn)

const complexData = {
  user: {
    id: 1001,
    profile: {
      name: '張三',
      age: 28,
      skills: ['JavaScript', 'Python', 'Go'],
      address: {
        country: '中國',
        city: '北京',
        district: '朝陽區(qū)',
      },
    },
    preferences: {
      theme: 'dark',
      language: 'zh-CN',
      notifications: {
        email: true,
        push: false,
        sms: true,
      },
    },
  },
  metadata: {
    createdAt: '2024-01-01T00:00:00.000Z',
    version: '1.2.0',
    features: ['auth', 'analytics', 'reporting'],
  },
};
// 不同縮進(jìn)級(jí)別的對(duì)比
console.log('無縮進(jìn)(壓縮):');
console.log(JSON.stringify(complexData));
console.log('\n縮進(jìn) 2 空格(推薦):');
console.log(JSON.stringify(complexData, null, 2));
console.log('\n縮進(jìn) 4 空格(詳細(xì)):');
console.log(JSON.stringify(complexData, null, 4));
console.log('\n縮進(jìn) 1 空格(緊湊):');
console.log(JSON.stringify(complexData, null, 1));

2. 字符串格式化 - 創(chuàng)意縮進(jìn)

const apiResponse = {
  status: 'success',
  data: {
    users: [
      { id: 1, name: '用戶A', active: true },
      { id: 2, name: '用戶B', active: false },
    ],
    pagination: {
      page: 1,
      limit: 10,
      total: 2,
    },
  },
  timestamp: '2025-09-15T10:30:00.000Z',
};
// 使用不同字符作為縮進(jìn)
console.log('使用箭頭縮進(jìn)(適合文檔展示):');
console.log(JSON.stringify(apiResponse, null, '→ '));
console.log('\n使用點(diǎn)號(hào)縮進(jìn)(適合層級(jí)展示):');
console.log(JSON.stringify(apiResponse, null, '··'));
console.log('\n使用豎線縮進(jìn)(適合樹狀結(jié)構(gòu)):');
console.log(JSON.stringify(apiResponse, null, '│ '));
console.log('\n使用制表符縮進(jìn)(適合代碼編輯器):');
console.log(JSON.stringify(apiResponse, null, '\t'));

3. 智能美化工具類

class JSONFormatter {
  constructor(options = {}) {
    this.options = {
      maxLineLength: options.maxLineLength || 80,
      arrayThreshold: options.arrayThreshold || 5,
      objectThreshold: options.objectThreshold || 3,
      colorOutput: options.colorOutput || false,
      showDataTypes: options.showDataTypes || false,
      ...options,
    };
  }
  format(data, space = 2) {
    // 智能判斷是否需要格式化
    const stringified = JSON.stringify(data);
    if (
      stringified.length <= this.options.maxLineLength &&
      !this.hasComplexStructure(data)
    ) {
      return stringified; // 簡(jiǎn)單數(shù)據(jù)保持單行
    }
    return JSON.stringify(data, this.createSmartReplacer(), space);
  }
  createSmartReplacer() {
    return (key, value) => {
      // 數(shù)組智能格式化
      if (Array.isArray(value)) {
        if (
          value.length <= this.options.arrayThreshold &&
          value.every((item) => typeof item !== 'object')
        ) {
          // 簡(jiǎn)單數(shù)組保持單行
          return value;
        }
      }
      // 對(duì)象智能格式化
      if (value && typeof value === 'object' && !Array.isArray(value)) {
        const keys = Object.keys(value);
        if (
          keys.length <= this.options.objectThreshold &&
          keys.every((k) => typeof value[k] !== 'object')
        ) {
          // 簡(jiǎn)單對(duì)象可以考慮緊湊格式
        }
      }
      // 數(shù)據(jù)類型注釋(調(diào)試模式)
      if (this.options.showDataTypes && value !== null) {
        if (typeof value === 'string' && key !== '') {
          return `${value} /* string */`;
        }
        if (typeof value === 'number' && key !== '') {
          return `${value} /* number */`;
        }
      }
      return value;
    };
  }
  hasComplexStructure(data) {
    const str = JSON.stringify(data);
    return str.includes('{') || str.includes('[') || str.includes('","');
  }
  // 調(diào)試專用格式化
  debug(data, label = 'Debug Output') {
    console.log(`\n=== ${label} ===`);
    console.log(this.format(data, 2));
    console.log(`=== End ${label} ===\n`);
    return data; // 支持鏈?zhǔn)秸{(diào)用
  }
  // 生成文檔示例
  generateDocExample(data, description = '') {
    const formatted = this.format(data, 2);
    return `${
      description ? `// ${description}\n` : ''
    }const example = ${formatted};`;
  }
  // 彩色輸出(終端環(huán)境)
  colorFormat(data) {
    if (!this.options.colorOutput) {
      return this.format(data);
    }
    const colors = {
      reset: '\x1b[0m',
      bright: '\x1b[1m',
      red: '\x1b[31m',
      green: '\x1b[32m',
      yellow: '\x1b[33m',
      blue: '\x1b[34m',
      magenta: '\x1b[35m',
      cyan: '\x1b[36m',
    };
    return JSON.stringify(
      data,
      (key, value) => {
        if (typeof value === 'string')
          return `${colors.green}${value}${colors.reset}`;
        if (typeof value === 'number')
          return `${colors.yellow}${value}${colors.reset}`;
        if (typeof value === 'boolean')
          return `${colors.blue}${value}${colors.reset}`;
        if (value === null) return `${colors.red}${value}${colors.reset}`;
        return value;
      },
      2
    );
  }
}
// 使用示例
const formatter = new JSONFormatter({
  maxLineLength: 60,
  arrayThreshold: 3,
  showDataTypes: true,
  colorOutput: true,
});
const testData = {
  simple: { a: 1, b: 2 },
  complex: {
    nested: {
      deep: {
        value: 'test',
      },
    },
  },
  array: [1, 2, 3, 4, 5, 6],
  simpleArray: ['a', 'b'],
};
console.log('智能格式化:');
console.log(formatter.format(testData));
console.log('\n調(diào)試輸出:');
formatter.debug(testData, 'Test Data Structure');
console.log('\n文檔示例:');
console.log(formatter.generateDocExample(testData.simple, '簡(jiǎn)單對(duì)象示例'));

特殊值處理

1. undefined、函數(shù)和 Symbol

const obj = {
  name: '測(cè)試',
  age: undefined,
  method: function () {
    return 'hello';
  },
  symbol: Symbol('test'),
  valid: true,
};
console.log(JSON.stringify(obj));
// 輸出: {"name":"測(cè)試","valid":true}
// undefined、函數(shù)和 Symbol 會(huì)被忽略

2. 數(shù)組中的特殊值

const arr = [1, undefined, function () {}, Symbol('test'), null, true];
console.log(JSON.stringify(arr));
// 輸出: [1,null,null,null,null,true]
// 數(shù)組中的 undefined、函數(shù)、Symbol 會(huì)被轉(zhuǎn)換為 null

3. NaN 和 Infinity

const data = {
  notANumber: NaN,
  infinity: Infinity,
  negativeInfinity: -Infinity,
  validNumber: 42,
};
console.log(JSON.stringify(data));
// 輸出: {"notANumber":null,"infinity":null,"negativeInfinity":null,"validNumber":42}

循環(huán)引用處理

1. 檢測(cè)和處理循環(huán)引用

const obj = { name: 'test' };
obj.self = obj; // 創(chuàng)建循環(huán)引用
// 這會(huì)拋出錯(cuò)誤
try {
  JSON.stringify(obj);
} catch (error) {
  console.log(error.message); // "Converting circular structure to JSON"
}
// 安全的循環(huán)引用處理
function safeStringify(obj) {
  const seen = new WeakSet();
  return JSON.stringify(obj, (key, value) => {
    if (typeof value === 'object' && value !== null) {
      if (seen.has(value)) {
        return '[Circular]';
      }
      seen.add(value);
    }
    return value;
  });
}
console.log(safeStringify(obj));
// 輸出: {"name":"test","self":"[Circular]"}

2. 復(fù)雜循環(huán)引用處理

class CircularHandler {
  constructor() {
    this.pathStack = [];
    this.seen = new WeakMap();
  }
  stringify(obj) {
    this.pathStack = [];
    this.seen = new WeakMap();
    return JSON.stringify(obj, (key, value) => {
      return this.handleValue(key, value);
    });
  }
  handleValue(key, value) {
    if (typeof value !== 'object' || value === null) {
      return value;
    }
    // 檢查循環(huán)引用
    if (this.seen.has(value)) {
      const path = this.seen.get(value);
      return `[Circular: ${path}]`;
    }
    // 記錄當(dāng)前路徑
    const currentPath =
      this.pathStack.length === 0
        ? 'root'
        : this.pathStack.join('.') + (key ? `.${key}` : '');
    this.seen.set(value, currentPath);
    // 添加到路徑棧
    if (key) this.pathStack.push(key);
    // 處理完成后從路徑棧移除
    setTimeout(() => {
      if (key) this.pathStack.pop();
    }, 0);
    return value;
  }
}
// 使用示例
const a = { name: 'A' };
const b = { name: 'B', ref: a };
a.ref = b; // 創(chuàng)建循環(huán)引用
const handler = new CircularHandler();
console.log(handler.stringify({ root: a }));

性能優(yōu)化

1. 大數(shù)據(jù)序列化優(yōu)化

class OptimizedStringify {
  constructor() {
    this.cache = new Map();
    this.cacheSize = 1000;
  }
  stringify(obj, options = {}) {
    const { useCache = true, chunkSize = 10000 } = options;
    // 緩存策略
    if (useCache) {
      const key = this.generateCacheKey(obj);
      if (this.cache.has(key)) {
        return this.cache.get(key);
      }
    }
    // 分塊處理大數(shù)組
    if (Array.isArray(obj) && obj.length > chunkSize) {
      return this.stringifyLargeArray(obj, chunkSize);
    }
    const result = JSON.stringify(obj);
    // 緩存結(jié)果
    if (useCache && result.length < 100000) {
      // 只緩存小于100KB的結(jié)果
      this.addToCache(this.generateCacheKey(obj), result);
    }
    return result;
  }
  stringifyLargeArray(arr, chunkSize) {
    const chunks = [];
    for (let i = 0; i < arr.length; i += chunkSize) {
      const chunk = arr.slice(i, i + chunkSize);
      chunks.push(JSON.stringify(chunk).slice(1, -1)); // 移除數(shù)組括號(hào)
    }
    return '[' + chunks.join(',') + ']';
  }
  generateCacheKey(obj) {
    // 簡(jiǎn)單的緩存鍵生成
    if (typeof obj === 'object' && obj !== null) {
      const keys = Object.keys(obj).sort();
      return keys.join(',') + '_' + typeof obj;
    }
    return String(obj);
  }
  addToCache(key, value) {
    if (this.cache.size >= this.cacheSize) {
      // 移除最老的緩存項(xiàng)
      const firstKey = this.cache.keys().next().value;
      this.cache.delete(firstKey);
    }
    this.cache.set(key, value);
  }
  clearCache() {
    this.cache.clear();
  }
}
// 使用示例
const optimizer = new OptimizedStringify();
const largeArray = new Array(50000)
  .fill(0)
  .map((_, i) => ({ id: i, value: `item${i}` }));
console.time('優(yōu)化版序列化');
const result1 = optimizer.stringify(largeArray);
console.timeEnd('優(yōu)化版序列化');
console.time('標(biāo)準(zhǔn)序列化');
const result2 = JSON.stringify(largeArray);
console.timeEnd('標(biāo)準(zhǔn)序列化');
console.log('結(jié)果一致:', result1 === result2);

2. 性能監(jiān)控

class PerformanceMonitor {
  static monitor(obj, label = 'JSON.stringify') {
    const startTime = performance.now();
    const startMemory = this.getMemoryUsage();
    const result = JSON.stringify(obj);
    const endTime = performance.now();
    const endMemory = this.getMemoryUsage();
    const metrics = {
      label,
      duration: (endTime - startTime).toFixed(2) + 'ms',
      outputSize: result.length,
      memoryDelta: endMemory - startMemory,
      throughput:
        ((result.length / (endTime - startTime)) * 1000).toFixed(0) +
        ' chars/s',
    };
    console.table(metrics);
    return result;
  }
  static getMemoryUsage() {
    if (typeof process !== 'undefined' && process.memoryUsage) {
      return process.memoryUsage().heapUsed;
    }
    return 0; // 瀏覽器環(huán)境
  }
  static benchmark(obj, iterations = 100) {
    const times = [];
    for (let i = 0; i < iterations; i++) {
      const start = performance.now();
      JSON.stringify(obj);
      const end = performance.now();
      times.push(end - start);
    }
    const avgTime = times.reduce((a, b) => a + b) / times.length;
    const minTime = Math.min(...times);
    const maxTime = Math.max(...times);
    console.log(`平均時(shí)間: ${avgTime.toFixed(2)}ms`);
    console.log(`最短時(shí)間: ${minTime.toFixed(2)}ms`);
    console.log(`最長時(shí)間: ${maxTime.toFixed(2)}ms`);
    return { avgTime, minTime, maxTime };
  }
}
// 使用示例
const testData = {
  users: new Array(1000).fill(0).map((_, i) => ({
    id: i,
    name: `用戶${i}`,
    data: new Array(100).fill(Math.random()),
  })),
};
PerformanceMonitor.monitor(testData, '大數(shù)據(jù)測(cè)試');
PerformanceMonitor.benchmark(testData, 50);

實(shí)際應(yīng)用場(chǎng)景

1. API 數(shù)據(jù)傳輸

class APISerializer {
  constructor() {
    this.compressionEnabled = true;
    this.maxResponseSize = 1024 * 1024; // 1MB
  }
  serializeResponse(data, version = 'v1') {
    const serializers = {
      v1: this.serializeV1.bind(this),
      v2: this.serializeV2.bind(this),
    };
    const serializer = serializers[version] || serializers.v1;
    let result = serializer(data);
    // 檢查響應(yīng)大小
    if (result.length > this.maxResponseSize) {
      console.warn('響應(yīng)數(shù)據(jù)過大,考慮分頁或數(shù)據(jù)壓縮');
      result = this.compressResponse(result);
    }
    return result;
  }
  serializeV1(data) {
    return JSON.stringify({
      status: 'success',
      data: data,
      timestamp: new Date().toISOString(),
    });
  }
  serializeV2(data) {
    return JSON.stringify(
      {
        success: true,
        result: data,
        meta: {
          timestamp: Date.now(),
          version: 'v2',
        },
      },
      null,
      this.compressionEnabled ? 0 : 2
    );
  }
  compressResponse(response) {
    // 簡(jiǎn)單的壓縮策略:移除不必要的空白
    return response.replace(/\s+/g, ' ').trim();
  }
}
// 使用示例
const apiSerializer = new APISerializer();
const userData = { id: 1, name: '張三', email: 'zhangsan@example.com' };
console.log('API v1 響應(yīng):');
console.log(apiSerializer.serializeResponse(userData, 'v1'));
console.log('\nAPI v2 響應(yīng):');
console.log(apiSerializer.serializeResponse(userData, 'v2'));

2. 配置文件生成

class ConfigGenerator {
  constructor() {
    this.templates = new Map();
    this.validators = new Map();
  }
  registerTemplate(name, template, validator = null) {
    this.templates.set(name, template);
    if (validator) {
      this.validators.set(name, validator);
    }
    return this;
  }
  generateConfig(templateName, values = {}) {
    const template = this.templates.get(templateName);
    if (!template) {
      throw new Error(`Template '${templateName}' not found`);
    }
    const config = this.mergeValues(template, values);
    // 驗(yàn)證配置
    const validator = this.validators.get(templateName);
    if (validator && !validator(config)) {
      throw new Error(`Configuration validation failed for '${templateName}'`);
    }
    return this.formatConfig(config, templateName);
  }
  mergeValues(template, values) {
    const result = JSON.parse(JSON.stringify(template)); // 深拷貝
    return this.deepMerge(result, values);
  }
  deepMerge(target, source) {
    for (const key in source) {
      if (
        source[key] &&
        typeof source[key] === 'object' &&
        !Array.isArray(source[key])
      ) {
        if (!target[key]) target[key] = {};
        this.deepMerge(target[key], source[key]);
      } else {
        target[key] = source[key];
      }
    }
    return target;
  }
  formatConfig(config, templateName) {
    const formatted = JSON.stringify(config, null, 2);
    const header = `// ${templateName} 配置文件\n// 生成時(shí)間: ${new Date().toISOString()}\n\n`;
    return header + formatted;
  }
}
// 注冊(cè)配置模板
const configGen = new ConfigGenerator();
configGen.registerTemplate(
  'database',
  {
    host: 'localhost',
    port: 5432,
    database: 'myapp',
    username: 'user',
    password: 'password',
    pool: {
      min: 2,
      max: 10,
      idle: 30000,
    },
    ssl: false,
  },
  (config) => {
    return config.port > 0 && config.pool.max > config.pool.min;
  }
);
configGen.registerTemplate('redis', {
  host: 'localhost',
  port: 6379,
  db: 0,
  keyPrefix: 'myapp:',
  ttl: 3600,
});
// 生成配置
console.log('數(shù)據(jù)庫配置:');
console.log(
  configGen.generateConfig('database', {
    host: 'prod-db.example.com',
    database: 'production_db',
    pool: { max: 20 },
  })
);
console.log('\nRedis配置:');
console.log(
  configGen.generateConfig('redis', {
    host: 'redis.example.com',
    keyPrefix: 'prod:',
  })
);

總結(jié)

這份基礎(chǔ)與進(jìn)階指南涵蓋了 JSON.stringify 的核心功能和實(shí)用技巧:

?? 掌握重點(diǎn)

  1. 基礎(chǔ)應(yīng)用 - 理解語法、參數(shù)和基本用法
  2. 選擇性序列化 - 掌握數(shù)據(jù)過濾和轉(zhuǎn)換技巧
  3. 格式化輸出 - 合理使用 space 參數(shù)提升可讀性
  4. 特殊值處理 - 了解各種數(shù)據(jù)類型的序列化行為
  5. 循環(huán)引用 - 學(xué)會(huì)檢測(cè)和處理循環(huán)引用問題
  6. 性能優(yōu)化 - 應(yīng)用緩存和分塊等優(yōu)化策略
  7. 實(shí)際應(yīng)用 - 在 API、配置等場(chǎng)景中靈活運(yùn)用

?? 下一步學(xué)習(xí)

接下來可以繼續(xù)學(xué)習(xí):

  • 與其他序列化方法的比較
  • 錯(cuò)誤處理與調(diào)試技巧
  • 安全性考慮與防護(hù)措施
  • 企業(yè)級(jí)最佳實(shí)踐
  • 開發(fā)工具與生態(tài)系統(tǒng)

通過掌握這些基礎(chǔ)與進(jìn)階知識(shí),你將能夠在實(shí)際項(xiàng)目中高效、安全地使用 JSON.stringify!

到此這篇關(guān)于JSON.stringify 基礎(chǔ)與進(jìn)階用法指南的文章就介紹到這了,更多相關(guān)JSON.stringify 用法內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論