我创建了这个函数,以便我可以将方法链接在一起:
export default function bindable(fn) {
return function boundFn(...args) {
return this === undefined ? fn(...args) : fn(this, ...args);
}
}
适用于bind operator。例如,您可以定义一个新函数,如
export const flatten = bindable(arrayOfArrays => Array.prototype.concat(...arrayOfArrays));
然后像这样使用它:
[[1,2,3],[4,5,6]]::flatten()
像这样或:
flatten([[1,2,3],[4,5,6]])
这开始很有效,直到我意识到如果我像第二种情况一样使用它,但是将辅助方法作为模块导入,它会破坏上下文!
import * as Arr from './array-helper-methods';
Arr.flatten([1,2,3]); // `this` is now `Arr`
所以我的问题是:有没有办法可以可靠地检测是否使用绑定操作符调用了函数?
答案 0 :(得分:2)
这是绑定运算符的一个很大但尚未解决的问题。但不,它只适用于方法。如果你想支持两种风格,你应该提供两个版本的功能。
动态地做这件事很难。不,您无法检测是否使用()
来调用该函数,作为一种方法,绑定了call
或apply
等等。您真的应该无论如何都不能。< / p>
对于你的情况,我会选择
function bindable(fn, isContext) {
return function boundFn(...args) {
return isContext(this) ? fn(this, ...args) : fn(...args);
}
}
export default bindable(bindable, f => typeof f == "function");
然后,您可以将bindable(flatten, Array.isArray)
或flatten::bindable(Array.isArray)
用于flatten
。对于更复杂的情况,您还可以合并函数的arity,即fn.length + 1 == args.length
。
答案 1 :(得分:1)
这是一种解决方法而不是真正的解决方案,但您可以检查this
是否包含flatten
属性:
export default function bindable(fn) {
return function boundFn(...args) {
return (this === undefined || 'flatten' in this) ? fn(...args) : fn(this, ...args);
}
}
答案 2 :(得分:1)
更通用(但性能不太好)的解决方案是检查this
的任何方法是否为boundFn
函数:
export default function bindable(fn) {
return function boundFn(...args) {
return (this == null || Object.values(this).some(x => x === boundFn))
? fn(...args)
: fn(this, ...args);
}
}