gpt4 book ai didi

javascript - 确定绑定(bind)的 JavaScript 函数是否是函数的绑定(bind)版本

转载 作者:行者123 更新时间:2023-12-01 16:25:31 25 4
gpt4 key购买 nike

假设我有一个函数foo,以及它的绑定(bind)版本bar。有没有内置方法可以比检查名称更明确地测试 bar 是否是 foo 的绑定(bind)版本?

function isBoundTo(bound, fn) {
return /bound (.+)$/.exec(bound.name)[1] === fn.name;
}

function foo() {
return this && this.x !== undefined ? this.x : 'foo';
}

function notfoo() {
return 'notfoo';
}

const bar = foo.bind({ x: 'bar' });
const boundbar = bar.bind({ x: 'boundbar' });

const baz = {
foo() {
return 'baz.foo';
}
};

const results = [
['foo()'],
['notfoo()'],
['bar()'],
['boundbar()'],
['baz.foo()'],
['isBoundTo(bar, foo)'],
['isBoundTo(bar, notfoo)'],
['isBoundTo(boundbar, bar)'],
['isBoundTo(boundbar, foo)'],
['isBoundTo(bar, baz.foo)', 'false positive'],
].reduce((obj, [exp, comment]) => {
const val = eval(exp);
return {
...obj,
[exp]: {
result: typeof val === 'string' ? JSON.stringify(val) : val,
comment: comment || ''
}
};
}, {});

console.table(results);
document.querySelector('.as-console-table thead th').innerText = 'expression';
/*<ignore>*/console.config({maximize:true,timeStamps:false,autoScroll:false});/*</ignore>*/
<script src="https://gh-canon.github.io/stack-snippet-console/console.min.js"></script>

我知道我可以用代理覆盖 Function.prototype.bind。我宁愿不这样做(尽管我对这个问题的研究越多,我就越不反对使用代理)。

Function.prototype.bind = new Proxy(Function.prototype.bind, {
apply: function (target, thisArg, args) {
let fn = Reflect.apply(target, thisArg, args);

Object.defineProperty(fn, 'targetFunction', {
value: thisArg.targetFunction || thisArg,
configurable: false,
writable: false
});

return fn;
}
});

function foo() {
return this && this.x !== undefined ? this.x : 'foo';
}

function notfoo() {
return 'notfoo';
}

const bar = foo.bind({ x: 'bar' });
const boundbar = bar.bind({ x: 'boundbar' });

const baz = {
foo() {
return 'baz.foo';
}
};

const results = [
'foo()',
'notfoo()',
'bar()',
'boundbar()',
'baz.foo()',
'foo.targetFunction',
'bar.targetFunction === foo',
'bar.targetFunction === notfoo',
'boundbar.targetFunction === bar',
'boundbar.targetFunction === foo',
'bar.targetFunction === baz.foo'
].reduce((obj, exp) => {
const val = eval(exp);
return {
...obj,
[exp]: {
result: typeof val === 'string' ? JSON.stringify(val) : val
}
};
}, {});

console.table(results, ['expression', 'result']);
document.querySelector('.as-console-table thead th').innerText = 'expression';
/*<ignore>*/console.config({maximize:true,timeStamps:false,autoScroll:false});/*</ignore>*/
<script src="https://gh-canon.github.io/stack-snippet-console/console.min.js"></script>

当我对此进行调试并检查 fn 时,有一个属性列为 [[TargetFunction]],但我不知道如何引用它。它似乎不是一个符号(表示为 [Symbol('name')])。我认为它可能是 Node.JS 特有的,但它也出现在 Chrome 中。它没有出现在 Firefox 中,但由于我只是在 Node 中使用它进行测试,所以我并不关心。我想如果调试器知道它存在并且可以检索它的值,它一定可以以某种方式访问。

编辑

因为你们中的一些人希望我证明这样做的必要性,我写了一个我正在做的事情的简化版本。 (我没有选择打开对话框的模式,但我确实需要测试它。) 注意:代码实际上并没有运行,因为 repl.it 不允许我安装 Enzyme 所需的依赖项。 https://repl.it/repls/BitesizedWeirdElectricity

最佳答案

没有办法做到这一点。 [[TargetFunction]] 是内部属性,未公开。

但是,您可以实现一个自定义的 bind 函数来跟踪:

const boundFns = new WeakMap()
function bind(fn, thisArg, ...args){
const newFn = function (...moreArgs) {
const allArgs = args.concat(moreArgs)
return new.target
? Reflect.construct(fn, allArgs, new.target)
: Reflect.apply(fn, thisArg, allArgs)
}
Object.defineProperty(newFn, 'name', {value: 'bound ' + fn.name})
Object.defineProperty(newFn, 'length', {value: fn.length})
Object.defineProperty(newFn, 'toString', {
value: function toString(){
return fn.toString()
},
configurable: true
})
boundFns.set(newFn, fn)
return newFn
}

function getTargetFunction(fn){
return boundFns.get(fn)
}

或者更简单(如 @Ry- pointed out ),使用原生 bind:

const boundFns = new WeakMap()
function bind(fn, ...args){
const newFn = fn.bind(...args)
boundFns.set(newFn, fn)
return newFn
}

function getTargetFunction(fn){
return boundFns.get(fn)
}

关于javascript - 确定绑定(bind)的 JavaScript 函数是否是函数的绑定(bind)版本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62378541/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com