javascript - 过度使用 Object.prototype.toString.call?

标签 javascript

我刚刚看到一个blog post与代码

if(Object.prototype.toString.call(callback) !== '[object Function]'){
    return new TypeError(callback + ' is not a function');
};

在这种特定情况下,它看起来像是过度设计的,因为我们可以使用typeof回调。就这段代码而言,我认为没有任何情况 typeofcallback 不会给出正确的答案。更重要的是,原型(prototype)可能会被覆盖并开始给出错误的答案,而 typeof 则不能。

示例是:

Object.prototype.toString = function(){return '[Object String]';};
Object.prototype.toString.call([])
// logs "[Object String]"

问题:是否有任何情况(鉴于此行的目的,即检查变量是否为函数)typeof 会失败?

我认为它更正确、更语义化并且不会过度设计使用:

if(typeof callback !== 'function'){
    return new TypeError(callback + ' is not a function');
};

最佳答案

Object.prototype.toString 检查来自 ES5 及更早的时代,当时无法通过自定义 Symbol.toStringTag 实现伪造该方法的结果。然而即便如此,如果人们想要对这些测试非常严格,他们通常也必须在初始评估时获取对 toString 函数的引用,因为 Object.prototype.toString 本身可以被覆盖 - 就像 Function.prototype 一样。打电话。

今天,以这种方式执行类型检查永远没有意义,而且您是对的,即使在当时,通常也没有必要。然而,在过去,浏览器中有许多平台对象从 typeof 返回唯一的字符串,这可能是以这种方式执行测试的动机之一。今天只剩下一个这样奇怪的情况:typeof document.all 返回未定义,但它实际上是一个函数。

不过,您偏爱 typeof 的直觉仍然是正确的。在几乎所有代码中, document.all 的情况可能都不值得担心,即使是这样, toString 检查也不会可靠。真正可靠(偏执)检查的一个例子是:

var _Object = Object;

function isObject(value) {
  return _Object(value) === value;
}

function isFunction(value) {
  return typeof value === 'function' || (isObject(value) && typeof value === 'undefined');
}

console.log(isFunction(function() {})); // true
console.log(isFunction(document.all));  // true

因此,您标记为“问题”的部分的答案是肯定的,在一种情况下 typeof n === 'function' 返回一个误导性的字符串,历史上还存在其他情况。

<小时/>

更多元数据,关于“过度工程”问题:也许作者在过去的某个时候将其作为“最佳实践”学习,并且已经有一段时间没有对其进行审查了,因为,嘿,这是他们熟悉的东西,而且它虽然有更好的选择,但我不会称尴尬的 if 条件过度设计。至少对我来说,过度工程指的是比这更高层次的东西——架构选择等。难以重构的东西。

就我个人而言,我建议如果您正在编写经常执行早期输入验证的代码,那么避免直接使用 typeof 可能仍然是一个好主意。在 JS 中测试“类型”通常并不那么简单,因此像上面示例中的那样的 isSomething 函数集合可以帮助抽象出更奇怪的实现细节,并恢复一些一致性和可读性。作为函数,它们也更加灵活(例如 arr.filter(isFunction) )。有一些流行的库提供了此类实用程序,如果使用它们,您通常不需要担心它是如何实现的。

关于javascript - 过度使用 Object.prototype.toString.call?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58262940/

相关文章:

javascript - dojo.io.iframe 上传文件时出错

javascript - 为什么不将全局变量值传递给函数?

javascript - 在 MySQL 查询中使用 javascript run select 选项

javascript - 如何在Android中读取有效的base64文件? ( Cordova )

javascript - 使用变量按类或 ID 查找对象

php - Facebook 应用程序 - 如何发送应用程序建议并直接在用户墙上发布

javascript - 导航元素不会延伸到父元素的高度

c# - 在 WinForms WebBrowser 控件中禁用 javascript?

javascript - 如何删除 dojo dijit 布局选项卡上的选择突出显示 css

javascript - 通过嵌套的JSON数组对象nodejs解析