本文已参与「新人创作礼」活动,一起开启掘金创作之路。
话说那天正在摸鱼中,同事在群里扔了一串代码,如下代码片段
(!(~+[])+{})[--[~+""][+[]]*[~+[]]+~~!+[]]+({}+[])[[~!+[]]*~+[]]
其实这串代码早在之前见过,也知道会输出什么,但是不知道其原理,索性今天就扒一扒到底是怎么回事,那下面就让我们来一探究竟吧,嘻嘻~
- 主要用到的知识点:隐式强制类型转换,按位取反运算
首先让我们来拆分一下,可以拆分为两大部分
第一部分(一丢丢长)
(!(~+[])+{})[--[~+""][+[]]*[~+[]]+~~!+[]]
再把第一部分进行拆分
①(!(~+[])+{})
先计算最里面的括号js(~+[]) "+"号隐式强制类型转换,所以+[]结果为0,接下来计算~0,
涉及到按位取反运算的计算规则
1、二进制数在内存中以补码的形式存储
2、按位取反:二进制每一位取反,0变1,1变0。
3、在计算机中一个整型数4字节,1字节8位,所以数字10在计算机中存储占32位,即00000000 00000000 00000000 00001010,
4、对于~10,在计算机中存储为
11111111 11111111 11111111 11110101 (这是10取反的结果,但却是未知数X的补码形式)
先取反,得
00000000 00000000 00000000 00001010 (此处,再次取反,返回10)
再加1,得
00000000 00000000 00000000 00001011 (10+1得11)
最高位变1,即
10000000 00000000 00000000 00001011 (取相反数即-11)
结果是“-11”
由此我们可以看出规律:“~x”的结果为“-(x+1)”
所以上述的~0根据规律可得为-1 然后,接着算!(-1) 这个显而易见为false,不过此时的false还是为布尔类型的, 所以有了接下来的运算(false + {})= 'false[object Object]', 及变为了字符串。
接着计算拆分后的剩余部分
② [--[~+""][+[]]*[~+[]]+~~!+[]]
1)先算--[~+""][+[]]
从简单的来[+[]] 显而易见为[0][~+""] = [-1], 也很简单,最后--[-1][0] = -2 ,这里有些疑惑 希望得到解答,哈哈。
嘻嘻,同事的解答来了。因为[-1][0] = -1,let a = -1, let b = --a, 所以b = -2。
2)[~+[]] 显而易见 为-1,所以--[~+""][+[]]*[~+[]] = -2 * -1 = 2。
3)~~!+[],这部分先计算!+[] = !0 = 1, 那么~~1还是等于1(~~ 这个是我们常用的)
所以最后这个剩余部分的结果为[3]。 结合上述,我们第一大部分的结果就出来了'false[object Object]'[3] = 's'。
有了上一部分的铺垫,第二部分就简单很多
所以,第二部分开始了
({}+[])[[~!+[]]*~+[]]
还是一样,也将第二部分再次进行拆分
-
({}+[])这里面我理解的是一个空的代码块加上了一个空的数组,结果为'[object Object]'。因为加号的原因,所以是字符串,这里的空数组可以换成空字符串(或者字符串,如果加字符串 结果就为'[object Object]这里是你写的字符串') -
[[~!+[]]*~+[]]一样先从里往外算~!+[]:!+[] = !0 = 1,~1 = -2~+[]结果为-1 有了上面多次计算,已经不难了这一小部分的结果为[-2 * -1] = [2]
那么,第二部分最后的结果为'[object Object]'[2] = 'b';
所以,整个的输出结果就。。。。嘻嘻 快去玩起来吧~