在函数之间传递元数据

问题描述:

我使用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') 
+0

真的很好,只要功能还没有使用'this' –

+0

耶不幸的是,已经有一个背景下,虽然我可以只添加隐藏属性,这种情况下,问题是,我必须设置,然后取消设置属性,因为这是在该上下文中的方法,并且属性值只与方法调用的生命周期有关......最好将它作为参数传递。 –

+1

我打算带出代码,以便清楚发生了什么 –

你可以只添加一个新的未公开的参数进行到底。 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)

+0

大问题,因为那么我的代码可能会认为额外的参数来自用户,而不是从我的库,然后抛出一个错误,说用户使用lib错误。如果用户通过4个变量而不是3个变量,那么我会在第4个变量中选择错误的变量? :)你可以看到各种各样的潜在问题。 –

+0

我编辑了原始答案,我当前的解决方案取决于API中已经具有在函数之间传递的选项对象的API。但这不是一个通用的解决方案,因为并不是所有的API都有一个对象对象被传递,尽管如果你向你的API添加一个选项obj,它可能会工作! –

+1

我认为任何答案都不是100%。彼得的回答并不是傻瓜。两者仍然允许调用者传递内部数据,但使其不太可能。我更喜欢我的,因为如果你的函数依赖于'this',并且你可以不用'call'或'apply'来调用它,它仍然可以工作 –