首页 > 技术文章 > js骚操作骂人不带脏

nxmin 2018-10-01 11:56 原文

前言

很多小伙伴们觉得javaScript很简单,下面的这行 javaScript代码可能会让你怀疑人生。


(!(~+[])+{})[--[~+""][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~+[]]

QQ截图20181001103352.png

小伙伴们学会了,以后遇到一些讲不通道理,让你不开森的人就把这段代码发给他。

那么这段代码为什么会输出sb呢?

其实这段代码考的是js的类型转化的一些基本原理

首先要运用到的第一个知识就是js运算符的优先级,因为这么长一段运算看的人眼花,我们必须得先根据优先级分成n小段,然后再各个击破

1, js运算符的优先级

优先级的排列如下表:

  优先级从高到低:838ba61ea8d3fd1fc89cb337364e251f95ca5f21.jpg

根据此规则,我们把这一串运算分为以下16个子表达式:
2e2eb9389b504fc28eefa108e3dde71190ef6d0e.jpg

运算符用红色标出,有一点可能大家会意识不到,其实中括号[]也是一个运算符,用来通过索引访问数组项,另外也可以访问字符串的子字符,有点类似charAt方法,如:'abcd'[1] // 返回'b'。而且中括号的优先级还是最高的哦。

接下来需要运用的就是javascript的类型转化知识了,我们先说说什么情况下需要进行类型转化。当操作符两边的操作数类型不一致或者不是基本类型(也叫原始类型)时,需要进行类型转化。

让我们快速的复习一下.在JavaScript中,一共有两种类型的值:原始值(primitives)和对象值(objects).

  • 原始值有:undefined, null, 布尔值(booleans), 数字(numbers),还有字符串(strings).
  • 其他的所有值都是对象类型的值,包括数组(arrays)和函数(functions).

2.类型转化

(1)先按运算符来分一下类:

  • 减号-,乘号*,肯定是进行数学运算,所以操作数需转化为number类型。

  • 加号+,可能是字符串拼接,也可能是数学运算,所以可能会转化为number或string

  • 一元运算,如+[],只有一个操作数的,转化为number类型

(2)下面来看一下转化规则。

(2).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).2 通过ToNumber()将值转换为数字

通过ToNumber()把值转换成Number,直接看ECMA 9.3的表格

| 参数 | 结果|
| ------------- |:-------------

推荐阅读