JavaScript中JSON.stringify结果不一致问题排查求助
动态菜单分类筛选异常排查
问题简述
开发网站动态菜单时,点击「早餐」按钮筛选对应分类食品出现异常:
- 预期
console.log(stringifyThis)输出9个'breakfast'字符串,且stringifyThis === 'breakfast'返回true - 实际
stringifyThis === 'breakfast'返回false,typeof stringifyThis显示为string,且仅输出3次日志(而非9次)
相关代码片段
筛选食品分类函数
function filterOut(item) { let stringifyThis = JSON.stringify(this); if (Object.values(item).includes(stringifyThis)) { populate(item) } console.log(stringifyThis); }
绑定点击事件监听器函数
function clicked(btn) { btn.addEventListener('click', () => { switch(btn.dataset.id) { case 'all': menuItem.innerHTML = ''; menu.map(populate); break; case 'breakfast': menuItem.innerHTML = ''; menu.map(filterOut, 'breakfast'); break; case 'lunch': menuItem.innerHTML = ''; menu.map((i) => { if (Object.values(i).includes('lunch')) { populate(i) } }); break; case 'shakes': menuItem.innerHTML = ''; menu.map((i) => { if (Object.values(i).includes('shakes')) { populate(i) } }); break; default: console.log('default'); break; } }); }
菜单数组示例
const menu = [ { id: 1, title: "buttermilk pancakes", category: "breakfast", price: 15.99, img: "./images/item-1.jpeg", desc: `I'm baby woke mlkshk wolf bitters live-edge blue bottle, hammock freegan copper mug whatever cold-pressed `, }, { id: 2, title: "diner double", category: "lunch", price: 13.99, img: "./images/item-2.jpeg", desc: `vaporware iPhone mumblecore selvage raw denim slow-carb leggings gochujang helvetica man braid jianbing. Marfa thundercats `, }, { id: 3, title: "godzilla milkshake", category: "shakes", price: 6.99, img: "./images/item-3.jpeg", desc: `ombucha chillwave fanny pack 3 wolf moon street art photo booth before they sold out organic viral.`, } ]
问题原因
this的包装对象问题:Array.map()的第二个参数用于绑定回调函数的this值,但传入原始类型字符串'breakfast'时,JS会自动将其包装成String对象(而非原始字符串)。此时JSON.stringify(this)会把对象序列化为"\"breakfast\""(带双引号的字符串),因此和原始的'breakfast'严格不相等。- 日志次数误解:示例中
menu数组仅包含3个元素,map()只会遍历3次,所以console.log只会输出3次,不可能输出9次。
解决方案
方案1:修正filterOut函数的this处理
将包装对象转回原始字符串,无需使用JSON.stringify:
function filterOut(item) { // 把String包装对象转为原始字符串 const category = String(this); if (Object.values(item).includes(category)) { populate(item); } console.log(category); console.log(category === 'breakfast'); // 现在返回true }
方案2:统一代码风格(推荐)
和lunch、shakes的处理逻辑保持一致,使用内联判断,避免this绑定的问题:
case 'breakfast': menuItem.innerHTML = ''; menu.map((i) => { if (Object.values(i).includes('breakfast')) { populate(i); } }); break;
内容的提问来源于stack exchange,提问作者Pandofla
相关产品推荐
相关产品推荐

