如何检测一个函数是正常调用还是作为标记模板文字?

时间:2019-07-04 15:39:04

标签: javascript ecmascript-6 template-literals tagged-templates

我想创建一个可以正常调用的函数:

myFn(arg1, arg2)

或作为标记的模板文字:

myFn`text ${someVar}`

myFn的实现中,是否可以检测到它是被正常调用还是作为标记模板文字?传递给模板文字的参数具有某种模式(第一个参数是字符串数组,其他参数(如果存在)将比第一个参数的数组长度少一个),因此我可以基于。但是从理论上讲,有人可以将相同的参数模式传递给正常的函数调用。

除了参数模式检测之外,还有什么特殊的方法可以检测它的调用方式?

1 个答案:

答案 0 :(得分:2)

我认为没有绝对确定的检查方法,但是您可以在参数检查中添加一些内容,以减少被满足您要求的参数意外调用的可能性。如果被称为模板标记,则第一个参数将是一个至少包含一个元素的数组,将被冻结,并且将具有一个名为raw的属性,该属性是一个长度相同的数组。如您已经提到的,您还可以检查剩余参数的数量:

function myFn ( arg1, ...rest ) {
  const isTag = !!(
    arg1 && arg1.length > 0 && arg1.raw && arg1.raw.length === arg1.length &&
    Object.isFrozen( arg1 ) &&
    rest.length + 1 === arg1.length
  );

  console.log( isTag );
}

// isTag === true
myFn`test`;
myFn`${0} ${1}`;
myFn``;

// isTag === false
myFn( );
myFn( ['test'] );

您可以通过验证数组和raw中的元素都是字符串,甚至在用适当的字符替换原始字符串中的转义序列后检查它们是否为相同的字符串,来进一步说明。我认为这可能是不必要的,因为这不会使有人故意欺骗您的功能(尽管它将限制他们可以用来欺骗它的输入)变得更加困难,并且除非除非除非有人试图故意欺骗它。