JSON.stringify() bỏ qua function (và undefined, Symbol) khi serialize object. Để giữ function, phải chuyển thành string trước.
Vấn đề: Function bị mất
<script>
const person = {
name: function() { return 'Ram + Rahim'; },
designation: 'Developer',
city: 'Hyderabad'
};
const json = JSON.stringify(person);
document.write(json);
// {"designation":"Developer","city":"Hyderabad"} — name function MẤT
</script>
Giải pháp: Chuyển function → string trước khi stringify
<script>
const obj = {
name: function() { return 'Ram + Rahim'; },
designation: 'Developer',
city: 'Hyderabad'
};
// Chuyển function thành string representation
obj.name = obj.name.toString();
const json = JSON.stringify(obj);
document.write(json);
// {"name":"function () { return 'Ram + Rahim'; }","designation":"Developer","city":"Hyderabad"}
</script>
Cách khôi phục (Reviver) — Không khuyến khích cho production
const json = '{"name":"function () { return 1+2; }","value":10}';
const obj = JSON.parse(json, (key, value) => {
if (typeof value === 'string' && value.startsWith('function')) {
return eval('(' + value + ')'); // ⚠️ RỦI RO XSS — chỉ dùng trusted source
}
return value;
});
console.log(obj.name()); // 3
Cách tốt hơn: Không serialize function
Thiết kế data transfer không chứa function. Function là behavior, không phải data.
Pattern: Serialize data, attach behavior sau
// Server gửi data thuần
const userData = { name: 'Alice', role: 'admin', permissions: ['read','write'] };
// Client attach behavior
function createUser(data) {
return {
...data,
can(permission) {
return this.permissions.includes(permission);
},
getDisplayName() {
return `${this.name} (${this.role})`;
}
};
}
const user = createUser(userData);
user.can('read'); // true
Lưu ý
toString()trên function trả về source code (nếu không phải native) — có thể chứa comment, formatting khác nhau cross-engine.eval()để revive function — rủi ro bảo mật nghiêm trọng.- Circular reference:
JSON.stringifythrow error — dùngflattedlibrary hoặc custom replacer.