在 JavaScript 中的 POJO 到底是什么?
关于 POJO 在 JavaScript 中是什么存在很多争论: StackOverflow 认为它是任何包含用户数据的类 ,但 Google 上的顶级 npm 模块 将 POJO 定义为 原型 为 Object.prototype
。
POJO 背后的直觉是 POJO 是一个只包含数据的对象,而不是方法或内部状态。 大多数 JavaScript 代码库都考虑使用花括号创建的对象 {}
成为 POJO。 然而更严格的代码库有时会 通过调用来 Object.create(null)
避免 从内置继承 Object
类 。
// If you create an object `obj` with `{}`, `obj` is an instance of
// the `Object` class, and so it has some built-in properties.
let obj = {};
obj.hasOwnProperty; // [Function]
obj.constructor === Object; // true
// On the other hand, `Object.create(null)` creates an object that
// doesn't inherit from **any** class.
obj = Object.create(null);
typeof obj; // 'object'
obj.hasOwnProperty; // undefined
obj.constructor; // undefined
obj.prop = 42;
obj.prop; // 42
POJOs 与 Maps
JavaScript Maps 是 POJO 存储数据的替代方案,因为它们没有任何继承自 Object
类。 但是,对象通常比映射更容易使用,因为并非所有 JavaScript 函数、框架和库都支持映射。
例如 JSON.stringify()
函数 不会序列化地图。
const map = new Map([['answer', 42]]);
JSON.stringify(map); // '{}'
检查对象是否为 POJO
检查一个对象是否是 POJO 可能有点棘手,这取决于您是否考虑使用创建的对象 Object.create(null)
成为 POJO。 最安全的方法是使用 Object.getPrototypeOf()
函数,并比较对象的原型。
function isPOJO(arg) {
if (arg == null || typeof arg !== 'object') {
return false;
}
const proto = Object.getPrototypeOf(arg);
if (proto == null) {
return true; // `Object.create(null)`
}
return proto === Object.prototype;
}
isPOJO({}); // true
isPOJO(Object.create(null)); // true
isPOJO(null); // false
isPOJO(new Number(42)); // false
比如下面是 Mongoose 的内部 isPOJO()
功能
exports.isPOJO = function isPOJO(arg) {
if (arg == null || typeof arg !== 'object') {
return false;
}
const proto = Object.getPrototypeOf(arg);
// Prototype may be null if you used `Object.create(null)`
// Checking `proto`'s constructor is safe because `getPrototypeOf()`
// explicitly crosses the boundary from object data to object metadata
return !proto || proto.constructor.name === 'Object';
};
Mongoose 检查 constructor.name
属性而不是检查是否 proto.constructor === Object
支持使用 Node.js vm
模块 。
const obj = require('vm').runInNewContext('({})');
// `obj` inherits from a different JavaScript context's `Object` class.
obj.constructor === Object; // false
obj.constructor.name; // 'Object'
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
上一篇: 跨域资源共享 CORS 的简要概述
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论