-1

这是这个问题的延续,但对于 ARRAYS。假设我想用 2 个参数调用数组函数,例如

console.log(
  [3,4,5].slice(1,2)
)

在第一步中,我将字符集减少为jsfuck约定,其中我们有 6 个可用字符:([]()!+为了清楚起见:az AZ 字母被"(JS 字符串)和数字包围 - 很容易转换为这 6 个字符):

console.log(
  [3,4,5]["slice"](1,2)
)

这里的问题是逗号(禁止字符),但我们可以通过使用trincot发现的以下巧妙技术来克服这个问题:

console.log(
  [1]["concat"](2)["reduce"]([]["slice"]["bind"]([3,4,5]))
)

但新的问题出现了:

可以调用具有 2 个(或更多)参数的函数序列而不嵌套它们(这是由上述技术强加的),但是以“流动”方式,我们在右侧调用下一个函数,例如[3,4,5].slice(1,2).concat(6).. :(不使用 'eval' 之类的将字符串解释为代码的解决方案)?(对于具有一个参数的函数,例如[3,4,5].slice(1).concat(6):)

4

3 回答 3

1

将方法的主题包装在数组中的现有技术(此处提到)专门用于字符串,将“字符串”转换为 [“字符串”]。诀窍是在.split()没有参数的情况下使用。应用该技巧后,使用其他小技巧来应用所需的方法并允许链接结果并不难。

当然,既然主题是一个数组,我们就不能使用.split().

事实证明,您可以使用以下方法来实现数组:

console.log(
  [3, 4, 5].reduce([].constructor).slice(-1)
)

这是相当低效的,因为reduce实际上会迭代主题数组,破坏前一次迭代的结果,因此只有一次(最后一次)迭代的结果决定了结果。Array您可以使用构造函数(此处[].constructor)在一个数组中获得四个参数,这些参数传递给回调。由于第四个参数是原始数组,我们可以将其弹出:但是这会让我们保留原始数组。所以我们对它进行切片:这样我们就得到了嵌套数组。

将其与其他技巧一起使用,您将获得执行以下表达式[3,4,5].slice(1,2)

console.log(
  [3].concat(4).concat(5).reduce([].constructor)
     .slice(-1)
     .concat([[1].concat(2)])
     .reduce([].fill.apply.bind([].slice))
)

所有方法引用都可以用 ["method"] 表示法编写,这样您就可以使用 JSF 生成这些字符串文字:

console.log(
  [3]["concat"](4)["concat"](5)["reduce"]([]["constructor"])
     ["slice"](-1)
     ["concat"]([[1]["concat"](2)])
     ["reduce"]([]["fill"]["apply"]["bind"]([]["slice"]))
)

警告

此解决方案依赖于被调用的 reduce 回调。请注意,当主题数组只有一个元素时,它不会被调用。在这种情况下,reduce只返回原始数组,这是不希望的。此外,当主题数组为空时,此方法将产生异常。

于 2020-08-28T14:57:03.060 回答
1

在这里,我开发了自己的答案(基于trincot 的想法)-为清楚起见,我做了单独的答案。最后,我找到了适用于具有零个、一个和多个元素的数组的解决方案。所以关键问题:[3,4,5]用另一个数组包装输入数组以[[3,4,5]]仅使用右侧运算符进入“流动方式”:)

console.log(
       [].map([].constructor).concat([[[]]])[0].slice(-1)
)

console.log(
      [5].map([].constructor).concat([[[]]])[0].slice(-1)
)

console.log(
  [3,4,5].map([].constructor).concat([[[]]])[0].slice(-1)
)

完整解决方案:

console.log(
  [3,4,5]
    // call slice (repeat this pattern for multi-param methods)
    .map([].constructor).concat([[[]]])[0].slice(-1)
    .concat([[1,2]]).reduce([].slice.apply.bind([].slice))
    // next method call in "flow" style
    .concat(6)   
)

删除逗号、点后的最终代码

console.log(
  [3]["concat"](4)["concat"](5)
    ["map"]([]["constructor"])["concat"]([[[]]])[0]["slice"](-1)
    ["concat"]([[1]["concat"](2)])["reduce"]([]["slice"]["apply"]["bind"]([]["slice"]))
    ["concat"](6)   
)

于 2020-08-28T19:13:57.987 回答
1

在这里,我开发了 trincot 答案- 他的好解决方案在数组为空或只有一个元素的情况下存在问题。使用他的想法,我找到了解决一个元素问题的解决方案(但仍然存在空数组的问题)。

关键问题:将数组包装[1,2,3]到另一个数组中以进入[[1,2,3]]流动方式(没有代码包装) - 为此我们可以使用以下代码

console.log(
   [3,4,5].map([].constructor)[0].slice(-1)
)

console.log(
   [3].map([].constructor)[0].slice(-1)
)

所以完整的解决方案看起来像

console.log(
  [3,4,5]
    // call slice (repeat this pattern for multi-param methods)
    .map([].constructor)[0].slice(-1)
    .concat([[1,2]]).reduce([].slice.apply.bind([].slice))
    // next method call in "flow" style
    .concat(6)   
)

去掉逗号和点后的代码如下

console.log(
  [3]["concat"](4)["concat"](5)
    ["map"]([]["constructor"])[0]["slice"](-1)
    ["concat"]([[1]["concat"](2)])["reduce"]([]["slice"]["apply"]["bind"]([]["slice"]))
    ["concat"](6)   
)

于 2020-08-28T15:54:39.560 回答