在函数之间传递元数据
我使用Node.js创建了一个API,我不想让API更改,也不想向函数添加额外的参数。但是,库中的内部代码现在需要在内部API方法和外部方法之间发送一些元数据。在函数之间传递元数据
有没有办法通过某种方式JS不涉及参数/参数的函数之间(元)数据?
TL; DR,它会传递函数之间的元数据API的JS的目的,是不应该改变的签名真的很有用。 (一个技巧是如果每次调用函数时都创建函数,则可以将数据分配到函数对象本身,但在这种情况下不是这样(函数在每次调用时都不会创建)。)
我目前使用的技巧 - 这是不是一个很好的 - 有API中使用{}对象的选项。我在该对象对象“__preParsed”中传递隐藏属性。用户将像通常那样使用该对象对象,在幕后我使用它来记录一些他们不需要知道的事情。
确定这里是代码:
//公共API
beforeEach.cb = function (desc, opts, fn) {
const _args = pragmatik.parse(arguments, rules.hookSignature);
_args[ 1 ].cb = true;
return beforeEach.apply(ctx, _args);
};
beforeEach = function (desc, opts, aBeforeEach) {
handleSetupComplete(zuite);
const _args = pragmatik.parse(arguments, rules.hookSignature);
const obj = { //have to do this until destructuring works
desc: _args[ 0 ],
opts: _args[ 1 ],
fn: _args[ 2 ]
};
handleBadOptionsForEachHook(obj.opts, zuite);
return 'there is more code but I omitted it';
};
,你可以看到第一个方法调用第二,或者第二可以直接调用,都是公共的API。
我们需要分析的参数在这两个电话,但作为一个优化,我们不应该对其进行解析第二次,如果第二个方法是由第一,而不是直接调用。
我会用暂时的解决方法是:
beforeEach.cb = function (desc, opts, fn) {
const _args = pragmatik.parse(arguments, rules.hookSignature);
_args[ 1 ].cb = true;
_args[ 1 ].__preParsed = true;
return beforeEach.apply(ctx, _args);
};
的OPTS选择对象是公开的,但用户不会知道的__preParsed财产。内部API将会。
这样做的问题是,用户可以直接调用公共API而不使用选项对象,并且由于签名非常多可变参数,因此直到我用解析引擎解析它之后,我才真正知道它arg如果有的话是对象对象!
你可以滥用this
对象进行非参数的元数据在通过调用使用Function.prototype.call
的功能如下:
function inner (arg1, arg2) {
console.log('inner called with', arg1, arg2)
console.log('inner metadata', this._meta_count)
}
inner.call({_meta_count: 17}, 'ARG ONE', 'ARG TWO')
inner.call({_meta_count: 18}, 'ARG ONE B', 'ARG TWO B')
你可以只添加一个新的未公开的参数进行到底。 JavaScript不会在意,以前的调用仍然可以工作,为什么这对你来说是个问题?
如果要检查参数个数和投掷的错误,你可以期望隐藏的参数是用魔法属性的对象,如果不是的话,抛出错误。
function go(a, b, c, _internal) {
if (_internal && ! _internal.hasOwnProperty('_magic')) {
throw new Error('invalid internal parameter passed');
}
}
你可以得到多一点偏执和魔法属性存储为Symbol,那么调用者可能不是偶然的传递,他们将不得不nefariously作用。
function go(a, b, c, _internal) {
if (_internal && !_internal.hasOwnProperty(go.internalParamProp)) {
throw new Error('invalid internal parameter passed');
}
console.log("Internal param", _internal && _internal[go.internalParamProp])
}
// Symbol for the magic property name to avoid accidental passing of internal param
go.internalParamProp = Symbol('');
// Passing the internal param
// Uses JS syntax that is not yet supported in some browsers
// If it's a concern, use or var obj={}; obj[go.internalParamProp] = 45
go(1, 2, 3, {
[go.internalParamProp]: 45
})
// Regular call
go(1, 2, 3)
// Invalid call
go(1, 2, 3, 4)
大问题,因为那么我的代码可能会认为额外的参数来自用户,而不是从我的库,然后抛出一个错误,说用户使用lib错误。如果用户通过4个变量而不是3个变量,那么我会在第4个变量中选择错误的变量? :)你可以看到各种各样的潜在问题。 –
我编辑了原始答案,我当前的解决方案取决于API中已经具有在函数之间传递的选项对象的API。但这不是一个通用的解决方案,因为并不是所有的API都有一个对象对象被传递,尽管如果你向你的API添加一个选项obj,它可能会工作! –
我认为任何答案都不是100%。彼得的回答并不是傻瓜。两者仍然允许调用者传递内部数据,但使其不太可能。我更喜欢我的,因为如果你的函数依赖于'this',并且你可以不用'call'或'apply'来调用它,它仍然可以工作 –
真的很好,只要功能还没有使用'this' –
耶不幸的是,已经有一个背景下,虽然我可以只添加隐藏属性,这种情况下,问题是,我必须设置,然后取消设置属性,因为这是在该上下文中的方法,并且属性值只与方法调用的生命周期有关......最好将它作为参数传递。 –
我打算带出代码,以便清楚发生了什么 –