You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular传递对象时函数消失问题求助(TypeScript)

问题分析与解决方案

问题根源

JSON 序列化(JSON.stringify)不支持保留函数类型数据,所以你在 saveData 时将整个 profileService 实例存入 localStorage 时,shopItems 里的 action 函数会被直接丢弃。当 getData 读取并恢复数据后,shopItem 就没有了 action 方法,调用时自然报错导致按钮无反应。

解决方案

1. 分离状态数据与业务逻辑

移除 shopItems 中的 action 属性,通过物品唯一标识(比如 name)来映射对应的操作逻辑,避免将函数存入 localStorage。

修改 shopItems 结构

shopItems = [
  {
    type: 'Profile Photo',
    name: 'Hugo',
    price: 50,
    bought: false
  },
  {
    type: 'Profile Photo',
    name: 'Philips',
    price: 100,
    bought: false
  },
  {
    type: 'Profile Photo',
    name: 'Michael',
    price: 200,
    bought: false
  }
  // ...其他物品
];

在 profile.service.ts 中维护操作映射

// profile.service.ts
private itemActionMap: Record<string, () => void> = {
  'Hugo': () => { this.profilePhotos[2].bought = true; },
  'Philips': () => { this.profilePhotos[3].bought = true; },
  'Michael': () => { this.profilePhotos[4].bought = true; }
};

buyItem(shopItem) {
  console.log(shopItem);
  if (this.updatePoints() >= shopItem.price) {
    shopItem.bought = true;
    // 通过物品name匹配对应的操作并执行
    const action = this.itemActionMap[shopItem.name];
    action && action();
    // 执行完操作后保存数据
    this.saveData();
  }
}

2. 修正 localStorage 读写逻辑

不要直接序列化整个 service 实例,只提取需要持久化的状态数据(比如 shopItems、profilePhotos、用户积分等),避免混入不可序列化的内容。

// profile.service.ts
constructor() {
  this.getData();
}

resetGame() {
  this.initDefaultData();
  this.saveData();
}

saveData() {
  // 仅序列化需要持久化的状态字段
  const persistedData = {
    shopItems: this.shopItems,
    profilePhotos: this.profilePhotos,
    points: this.points // 假设你有用户积分属性
  };
  localStorage.setItem('profileService', JSON.stringify(persistedData));
}

getData() {
  const savedData = localStorage.getItem('profileService');
  if (savedData) {
    const parsedData = JSON.parse(savedData);
    // 逐个恢复状态字段,不覆盖service的方法和内部属性
    this.shopItems = parsedData.shopItems;
    this.profilePhotos = parsedData.profilePhotos;
    this.points = parsedData.points;
  } else {
    // 初始化默认数据
    this.initDefaultData();
  }
}

private initDefaultData() {
  // 初始化默认的物品、头像和积分
  this.shopItems = [/* 默认物品数组 */];
  this.profilePhotos = [/* 默认头像数组,初始bought状态为false */];
  this.points = 0;
}

3. 验证流程

点击 UNLOCK 按钮时,buyItem 会通过物品 name 匹配到对应的操作函数执行,同时 saveData 仅存储状态数据,不会丢失关键信息;getData 恢复数据后,业务逻辑由 service 内部的映射表维护,不会因为序列化丢失。

内容的提问来源于stack exchange,提问作者mtt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.11 22:01:06