考虑一个说明性例子:
function addSafely(weakset, value) {
if (canBeAddedToWeakSet(value)) {
weakset.add(value);
}
} 那么,在这种情况下,您认为实现canBeAddedToWeakSet函数的简洁和正确的方法是什么呢?表演也是一个很好的选择。
我现在使用以下实现,但我不确定它是否是一个完整的实现(即涵盖所有情况):
function canBeAddedToWeakSet(value) {
return !!value && (typeof value === 'object' || typeof value === 'function');
}UPD:,以下是那些对性能感兴趣的人的一些基准测试结果。
发布于 2017-09-21 10:02:32
请参阅ECMAScript 2015 (第6版,ECMA-262) WeakSet.add()
23.4.3.1 WeakSet.prototype.add (值) 采取了以下步骤:
- If e is not empty and SameValue(e, value) is true, then
-
- Return S.
正如第4项所述,它检查类型(ECMAScript语言类型) of value is Object是否为Object,因为typeof null也是“object”,因此函数canBeAddedToWeakSet应该是:
function canBeAddedToWeakSet(value) {
return value !== null && (typeof value === 'object' || typeof value === 'function');
}发布于 2017-09-21 10:20:40
根据ECMAScript规范表35,12.5.5.1节,允许typeof操作符返回主机对象的依赖于实现的字符串,这些对象是Object类型,尽管在这些情况下鼓励实现返回"object",但它们不需要这样做。
不鼓励实现为非标准的外来对象定义新的
typeof结果值。如果可能的话,应该对这些对象使用"object"。
有趣的表35的例外是document.all。这样的推理证明了故意违反规范的行为:
这种违反的动机是希望与两类遗留内容兼容:一种是使用
document.all的存在作为检测遗留用户代理的方法,另一种是只支持那些遗留用户代理,并且使用document.all对象而不首先测试它的存在。
我的建议是验证typeof value不返回保证不满足Type(value) of Object的字符串子集,并可选择地检查document.all是否存在。
function canBeAddedToWeakSet(value) {
switch (typeof value) {
case 'undefined':
return value !== undefined
case 'boolean':
case 'number':
case 'string':
case 'symbol':
return false
case 'object':
return value !== null
default:
return true
}
}发布于 2017-09-21 10:55:56
免责声明:这是微观优化。表演是每一种品质的敌人。在某些情况下,需要对其进行排序,但大多数情况下,您应该优先考虑简单性+可读性。
如果你真的需要在插入WeakSet之前检查一下.
WeakSet的规范说只有一个Object可以插入到WeakSet中。因此,问题是:“如何检查一个值是否为Object?”
在es6.weak-set.js库中( 巴贝尔-聚脂使用的)实现之后,有一个对_is-object.js的传递引用,该引用检查值是否为对象:
module.exports = function (it) {
return typeof it === 'object' ? it !== null : typeof it === 'function';
};因此,请放心,您的canBeAddedToWeakSet几乎和它一样好(尽管我会考虑这个三元优化并将它重命名为isObject)。
更新:您可能还想考虑注释中提到的逻辑优化(65 @Patrick!)。
在插入任何集合之前,您什么时候不应该检查是否正确?
如果您有严格的实时性能要求,您可能需要考虑避免对每个插入进行此检查。如果这是您的案例,下面是您的选择:
1)检查每个插入的
优点:防止调用者处理错误的值。
缺点:进行检查和分支预测的性能成本
2)尝试/捕捉
我会关心的是设置异常处理的开销,需要高性能的函数.
优点:保护调用者不处理错误的值。
缺点:尝试/捕获开销的高性能成本(比if语句更糟糕)
3)让调用方处理错误的值
这种策略是为了减少性能关键功能的责任。对于一些打电话的人来说,这张支票可能完全没有必要。例如,在一个域中,我可能知道我只会拥有对象或空。在这种情况下,调用add(myWeakset, value || {})是我最好的性能选择。
尽管如此,有些域可能需要addSafely的能力,因此公开这两种方法可能是有益的。
优点:调用者可以最大化其域的性能。
缺点:不负责任的来电者的风险和复杂性的增加
https://stackoverflow.com/questions/46340150
复制相似问题