在 JavaScript 中,可以使用多种方式判断一个对象是否是 Promise
。以下是几种常见的方法:
一、使用 typeof
和 then
方法
Promise
对象有 then
方法,我们可以通过 typeof obj.then === 'function'
来判断:
js
复制编辑
function isPromise(obj) {
return !!obj && typeof obj.then === 'function';
}
// 测试
console.log(isPromise(new Promise(() => {}))); // true
console.log(isPromise({ then: function() {} })); // true(但可能是类 Promise)
console.log(isPromise(null)); // false
console.log(isPromise(123)); // false
console.log(isPromise({})); // false
🔹 优点:简单可靠
🔹 缺点:可能会误判类似 Promise
的对象(例如手写的 thenable
对象)
二、使用 instanceof Promise
js
复制编辑
function isPromise(obj) {
return obj instanceof Promise;
}
// 测试
console.log(isPromise(new Promise(() => {}))); // true
console.log(isPromise(Promise.resolve(123))); // true
console.log(isPromise({ then: function() {} })); // false(不会误判 `thenable` 对象)
🔹 优点:更精准,能区分真正的 Promise
和 thenable
对象
🔹 缺点:无法判断跨 iframe
的 Promise
(不同 window
的 Promise
可能有不同的 prototype
)
三、结合 then
和 catch
(最严谨)
js
复制编辑
function isPromise(obj) {
return !!obj && typeof obj.then === 'function' && typeof obj.catch === 'function';
}
// 测试
console.log(isPromise(new Promise(() => {}))); // true
console.log(isPromise(Promise.resolve())); // true
console.log(isPromise({ then: function() {} })); // false(过滤掉 `thenable`)
console.log(isPromise({ then: () => {}, catch: () => {} })); // true(仍然能识别 `thenable`)
🔹 优点:既能识别 Promise
,也能识别符合 Promise
规范的 thenable
对象
🔹 缺点:仍可能被手写 then/catch
对象欺骗
四、使用 Object.prototype.toString
js
复制编辑
function isPromise(obj) {
return Object.prototype.toString.call(obj) === "[object Promise]";
}
// 测试
console.log(isPromise(new Promise(() => {}))); // true
console.log(isPromise(Promise.resolve())); // true
console.log(isPromise({ then: function() {} })); // false
console.log(isPromise({})); // false
🔹 优点:精准匹配 Promise
类型
🔹 缺点:对手写 thenable
兼容性不好
五、推荐的最佳实践
如果需要严格区分 Promise
和 thenable
,使用:
js
复制编辑
function isPromise(obj) {
return !!obj && (obj instanceof Promise || (typeof obj.then === "function" && typeof obj.catch === "function"));
}
这样既能识别 Promise
,又能兼容符合 Promise A+
规范的 thenable
对象。
六、总结
方法 | 适用场景 | 是否能识别 thenable | 可能误判 |
---|---|---|---|
typeof obj.then === 'function' | 快速判断 | ✅ | thenable |
obj instanceof Promise | 仅判断原生 Promise | ❌ | iframe 跨域问题 |
typeof obj.then === 'function' && typeof obj.catch === 'function' | 兼容 Promise A+ 规范 | ✅ | 伪造对象 |
Object.prototype.toString.call(obj) === "[object Promise]" | 精确匹配 Promise | ❌ | 不能识别 thenable |
最稳妥的方式是 instanceof Promise
或 then + catch
组合方式,具体选择哪种,取决于你的实际需求。