加入收藏 | 设为首页 | 会员中心 | 我要投稿 揭阳站长网 (https://www.0663zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 站长资讯 > 外闻 > 正文

毫无人性的刁钻面试题说起

发布时间:2021-04-20 17:31:46 所属栏目:外闻 来源:互联网
导读:法 直接 console.log 是不可能的,因为就算你用字符串拼出 console,你也沒办法像 PHP 那样拿字符串来执行函数。 那 eval 呢?evali 里面可以放字符串,可以是就可以。问题是我们也没法使用 eval,因为不能用英文字母。 还有什么方法呢?还可以用 function con

直接 console.log 是不可能的,因为就算你用字符串拼出 console,你也沒办法像 PHP 那样拿字符串来执行函数。

那 eval 呢?evali 里面可以放字符串,可以是就可以。问题是我们也没法使用 eval,因为不能用英文字母。

还有什么方法呢?还可以用 function constructor:new Function("console.log(1)") 来执行,但问题是我们也不能用 new 这个关键字,所以乍一看也不行,不过不需要 new 也可以,只用 Function("console.log(1)") 就可以创建一个能够执行特定代码的函数。

所以接下来的问题就变成了怎样才能拿到 function constructor,只要能拿到就有机会。

在 JS 中可以用 .Constructor 拿到某个对象的构造函数,例如 "".constructor 就会得到:ƒ String() { [native code] },如果你有一个函数,就能拿到 function constructor,像这样:(()=>{}).constructor,在这个问题中我们不能直接用 .constructor,应该用:(()=>{})['constructor']。

如果不支持 ES6 ,不能用箭头函数怎么办,还有办法得到一个函数吗?

有,而且很容易,就是各种内置函数,例如说 []['fill']['constructor'],其实就是 [].fill.constructor,或者是 ""['slice']['constructor'],也可以拿到 function constructor,所以这不是个问题,就算没有箭头函数也没关系。

一开始我们期望的代码是这样:Function('console.log(1)')(),用前面的方法改写的话,应该把前面的 Function 替换成 (()=>{})['constructor'],变成 (()=>{})['constructor']('console.log(1)')()只要想办法拼凑出这段代码问题就解决了。现在我们解决了第一个问题:找到执行函数的方法。

如何得到数字

接下来的数字就比较简单了。

这里的关键在与 js 的强制多态,如果你有看过 js 类型转换的文章,或许会记得 {} + [] 可以得出 0 这个数字。

假设你不知道这个,我来解释一下:利用 ! 这个运算符,可以得到 false,例如 1[]或者 !{} 都可以得出 false。然后两个 false 相加就可得到 0:![] + ![] ,以此类推,既然 ![] 是 false,那前面再加一个 !,!![] 就是 true,所以 ![] + !![] 就等于 false + true,也就是 0 + 1,结果就是 1。

或者用更简短的方法,用来 +[] 也可以利用自动类型转换得到 0 这个结果,那么 +!![] 就是 1。

有了 1 之后,就可以得到所有数字了,只要一直不断暴力相加就行了,如果不想这样做,也可以利用位运算 << >> 或者是乘号,比如说要凑出 8,就是 1 << 3,或者是 2 << 2,要凑出 2 就是(+!![])+(+!![]),所以 (+!![])+(+!![]) << (+!![])+(+!![]) 就是 8,只需要四个 1 就行了,不需要自己加 8 次。

不过现在可以先不考虑长度,只需要考虑能不能凑出来就行了,只要能得出 1 就足够了。

如何得到字符串

最后就是要想办法凑出字符串了,或者说要得到 (()=>{})['constructor']('console.log(1)')() 中的每一个字符。

怎样才能得到字符呢?答案是和数字一样,即强制多态。

(编辑:揭阳站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    热点阅读