程序员发了段代码,网友:先容你跑39米,40米的大刀收不回了!
程序员 — 一个互联网行业中最苦逼的一个职位。由于他们每天都要干很多的活,还要加很多的班,掉很多头发,背很多的黑锅(ps:我能怎样办我也很绝望啊!ヽ(≧□≦)ノ)。但是程序员每天敲敲代码,不会很枯燥吗?是的,假如作为一名程序员每天就只敲代码,确实很乏味。但是谁说程序员每天就只会敲代码呢?我们有我们的快乐,我们程序员骚起来,就没你们的事了。
比方:
(!(~+[])+{})[–[~+””][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~+[]]
假如你觉得某个人令你很不爽,于是,程序员就会发一段代码,我们来看看结果:
哈哈,是不是被骂了还在问人这段代码是什么意思呢?
我来告诉你:
这段代码为什么会输出sb呢?其实这段代码考的是js的类型转化的少量基本原理。
首先要运用到的第一个知识就是js运算符的优先级,由于这么长一段运算看的人眼花,我们必需得先根据优先级分成n小段,而后再各个击破。
这里还是要推荐下小编的web前台学习 群 : 687958461,不论你是小白还是大牛,小编我都欢迎,不定期分享干货,包括小编自己整理的一份最新的web前台资料和0基础入门教程,欢迎初学和进阶中的小伙伴。在不忙的时间我会给大家解惑。
1、js运算符的优先级
优先级的排列如下表,优先级从高到低:
根据此规则,我们把这一串运算分为以下16个子表达式:?
运算符用红色标出,有一点可能大家会意识不到,其实中括号[]也是一个运算符,用来通过索引访问数组项,另外也可以访问字符串的子字符,有点相似charAt方法,如:’abcd'[1] // 返回’b’。而且中括号的优先级还是最高的哦。
接下来需要运用的就是java的类型转化知识了,我们先说说什么情况下需要进行类型转化。当操作符两边的操作数类型不一致或者者不是基本类型(也叫原始类型)时,需要进行类型转化。
让我们快速的复习一下,在Java中,一共有两种类型的值:原始值(primitives)和对象值(objects)。
原始值有:undefined、null、布尔值(booleans)、数字(numbers)、还有字符串(strings)。
其余的所有值都是对象类型的值,包括数组(arrays)和函数(functions)。
2、类型转化
先按运算符来分一下类:
减号-,乘号*,一定是进行数学运算,所以操作数需转化为number类型。
加号+,可能是字符串拼接,也可能是数学运算,所以可能会转化为number或者string。
一元运算,如+[],只有一个操作数的,转化为number类型。
下面来看一下转化规则。
1、对于非原始类型的,通过
ToPrimitive()
将值转换成原始类型
ToPrimitive(input, PreferredType?)
可选参数PreferredType是Number或者者是String。返回值为任何原始值.假如PreferredType是Number,执行顺序如下:
假如input为primitive,返回;
否则,input为Object。调用
obj.valueOf()
。假如结果是primitive,返回;
否则,调用
obj.toString()
,假如结果是primitive,返回;
否则,抛出TypeError。
假如 PreferredType是String,步骤2跟3互换,假如PreferredType没有,Date实例被设置成String,其余都是Number。
2、通过ToNumber()将值转换为数字
通过ToNumber()把值转换成Number,直接看ECMA 9.3的表格:
假如输入的值是一个对象,则会首先会调用
ToPrimitive(obj,Number)
将该对象转换为原始值,而后在调用ToNumber()将这个原始值转换为数字。
3、通过ToString()将值转换为字符串
通过ToString()把值转化成字符串, 直接看ECMA 9.8的表格
假如输入的值是一个对象,则会首先会调用
ToPrimitive(obj,String)
将该对象转换为原始值,而后再调用ToString()将这个原始值转换为字符串.
规则就这么多,接下来实践一下,根据我们上面划分出的子表达式,一步一步将这个神奇的代码给执行出来。开工~
先看最简单的子表达式16:
+[]
只有一个操作数[],一定是转化为number了,根据上面的规则2,[]是个数组,object类型,即对象。所以得先调用toPrimitive转化为原始类型,并且PreferredType为number,这个参数表示更“倾向于”转化的类型,这里一定是number了。而后首先调用数组的valueOf方法,数组调用valueOf会返回自身,
这个时候,我们得到一个空串“”,还没有结束,看上面的规则2形容,继续调用toNumber,转化为number类型,
大功告成!子表达式16转化完毕,+[],最终得到0。
来看子表达式15:
[~+””]
空串””前面有两个一元操作符,但是操作数还是只有一个,所以,最终要转化为的类型是number。看规则2吧,空串调用toNumber得到0。接下来是~,这是个什么东东呢?它是位运算符,作用可以记为把数字取负而后减一,所以~0就是-1 。
别忘了,这个子表达式外头还包着中括号,所以最终的值为[-1],即一个数组,里面只有一个元素-1.
接下来看子表达式13就简单了
把15、16求出来的填进去,就变成了这样:
–[-1][0]
,取数组的第0个元素,而后自减,结果为-2,是不so easy!
继续往上走,子表达式14:
[~+[]]
其实把15、和16的原理用上就非常显著了,答案[-1]。
继续来求子表达式9,此刻它已变成:
-2*[-1]
,有稍许不一样,不过没关系,我们还是按照规则来,运算符是乘号*,当然是做数学运算,那后面的
[-1]
就得转化为number,与16的求法相似,过程如下:
调用toPrimitive,发现是object类型
调用valueOf,返回自身[-1]
由于不是原始类型,继续调用toString,返回”-1″
“-1″是原始类型了,而后调用toNumber,返回-1
与-2相乘,返回2
子表达式10:
~~!+[]
不多说了,答案1。就是从右往左依次一元计算。
有了9和10,我们来到了子表达式4,此刻它已经长这样了:2+1, 好,我不多说了。
继续看表达式7:
!(~+[]),~+[]=-1
这个根据上面已经知道了,那!-1是什么呢?这里要说一下这个感叹号,它是逻辑取非的意思,会把表达式转化为布尔类型,转化规则和js的Truthy和Falsy准则是一样的,后面跟数字的,除0以外都为false,后面跟字符串的,除空串以外都为false。这里的
!-1
当然就是false了。
接下来这个表达式3:false+{}有点关键
一个布尔加一个对象,那这个{}应该先转化为原始类型,流程如下:
调用toPrimitive,发现是object类型
调用valueOf,返回自身{},
不是原始类型,调用toString,返回
[objectObject]
false与
[objectObject]
相加,false先转化为字符串”false”
相加得结果
false[objectObject]
知道了表达式3和4,我们即可以来看表达式1了,此时它是这样的:
false[objectObject]
[3],由于这个[]可以取字符串的子字符,像charAt一样,所以得到了结果”s”
经过上面艰难的流程,我们拿到了字符”s”,也就是那张图的左半边,剩下的那个”b”,相同的原理可以搞出来,我这里就不逐个演示了,留给你练练吧~
回顾一下这个过程其实也不复杂,只是有少量需要重复劳动的,只需你掌握了运算的优先级,能把大串分解成一个个小串,而后运用类型转化的知识挨个解决就搞定了。怎样样,看到这里你还觉得神奇吗?
同样的,中文字符也是由这样组成的,跟英文同样的道理。
理解了吗?假如以后有人给你发这段代码,二话不说,平底锅伺候。哈哈。
1. 本站所有资源来源于用户上传和网络,如有侵权请邮件联系站长!
2. 分享目的仅供大家学习和交流,您必须在下载后24小时内删除!
3. 不得使用于非法商业用途,不得违反国家法律。否则后果自负!
4. 本站提供的源码、模板、插件等等其他资源,都不包含技术服务请大家谅解!
5. 如有链接无法下载、失效或广告,请联系管理员处理!
6. 本站资源售价只是摆设,本站源码仅提供给会员学习使用!
7. 如遇到加密压缩包,请使用360解压,如遇到无法解压的请联系管理员
开心源码网 » 程序员发了段代码,网友:先容你跑39米,40米的大刀收不回了!