在日常的 JS 编码过程中,可能很难看到相等运算符(=)是如何工作的。特别是当操作数具有不同类型时。这有时会在条件语句中产生一些难以识别的 bug。很容易理解为什么 0 == 8 是 flase 的或者 '' == false 是 true。但是为什么{} == true是 false 的就看不出来了。接下将会讲这是肿么肥事。
在这之前,先说几个术语:
操作符(Operator) 表示操作的符号。例如,相等运算符==比较两个值,三等运算符 === 比较两个值及其类型,加法运算符+两个数字和或连接两个字符串。
操作数(Operand) 是运算的主体,是执行运算的数量。例如,在表达式 0 == {} 中,0 是第一个操作数,{} 是第二个操作数。
JS 中的基本数据类型(原始类型)有 number,string, boolean,null 和 undefined,symbol。
全等和不全等操作符遵循以下基本规则(IEA规则):
规则很简单。
值得一提的是,在全等运算中,NaN 与其他任何值相比,结果都是 false。 来看看考虑些例子,这是学习这些规则的好方式。
例 1
1 === "1" // false, 规则 1
操作数是不同的类型(数字和字符串),基于 IEA 规则1,它们是不等的。
例 2
0 === 0 // true, 规则 6
操作数具有相同的类型和相同的值,因此根据IEA规则6,它们是严格相等的。
例 3
undefined === undefined // true, 规则 3
两个操作数都是 undefined 的,应用 IEA 规则3,它们是相等的。
例 4
undefined === null // false, 规则 1
因为操作数是不同的类型,根据IEA规则1,它们并不相同。
例 5
NaN === NaN // false, IEA 规则 5
操作数是相同的类型,但是IEA 规则4 表明任何与 NaN 比较都是不相等的。
例 6
var firstObject = {},
secondObject = firstObject;
secondObject['name'] = 'Neo';
secondObject === firstObject // true, IEA 规则 8
两个变量 firstObject 和 secondObject 都是对同一对象的引用,根据 IEA 规则8,它们相等。
例 7
[] === [] //false, IEA 规则 9
字面量 [] 创建了一个新的数组引用。这两个操作数是相同的类型(对象),但是它们引用不同的对象。根据 IEA 规则 9 ,它们不相等。
对象到布尔值
对象到布尔值的转换非常简单:所有的对象(包括数字和函数)都转换为 true。对于包装对象亦是如此:new Boolean(false) 是一个对象而不是原始值,它将转换为 true。
对象到字符串
对象到字符串 和 对象到数字 的转换都是通过调用待转换对象的一个方法来完成的。一个麻烦的事实是,JS 对象有两个不同的方法来执行转换,接下来要讨论的一些特殊场景更加复杂。值得注意的是,这里提到的字符串和对象的转换规则只适用于原生对象(native object)。宿主对象(例如有Web浏览器定义的对象)根据各自的算法可以转换成字符串和数字。
所有的对象继承了两个转换方法。第一个是toString(),它的作用是返回一个反映这个对象的字符串。默认的 toString()方法并不会返回一个有趣的值:
({x:1,y:2}).toString() //=>"[object object]"
很多类定义了更多特定版本的toString()方法。例如,数组的 toString() 方法是将每个数组元素转换为一个字符串,并在元素之间添加逗号后合并成结果字符串。
函数的 toString() 方法返回了这个函数的实现定义。实际上,这里的实现是通常是将用户定义的函数转换为 JS 源代码字符串。
日期 Date 的 toString() 方法返回了一个可读的日期和时间字符串。
RegExp 的 toString() 方法将RegExp对象转换为表示正则表达式直接量的字符串:
来几个例子:
[1,2,3].toString() //=> "1,2,3"
(function(x){ f(x); }).toString() // => "function(x){ f(x); }"
/\d+/g.toString() // => "/\d+/g"
new Date(2019,9,16).toString() //=> "Wed Oct 16 2019 00:00:00 GMT+0800 (中国标准时间)"
另一个转换对象的函数是 valueOf()。如果存在任意原始值,它就默认将对象转换为表示它的原始值。对象是复合值,而且大多数对象无法真正表示为一个原始值,因此默认的 valueOf() 方法简单地返回对象本身,而不是返回一个原始值。数组、函数和正则表达式简单地继承了这个方法,调用这些类型的实例的valueOf() 方法只是简单返回对象本身。日期 Date 的 valueOf() 方法会返回它的一个内部表示:1970年1月1日以来的毫秒数。
new Date(2019,9,16).valueOf() // 1571155200000
通过使用 toString() 和 valueOf() 方法,就可以做到对象到字符串和对象到数字的转换了。但需要注意的是,在某些特殊的场景中,JS 执行了完全不同的对象到原始值的转换。
JS 中对象到字符串的转换经过如下这些步骤,咱们简称 OPCA 算法。
当调用 valueOf() 方法时,大多数原生对象都会返回对象本身。因此 toString() 方法使用得更频繁。
关于 Date 对象的注意事项:在转换为原始值时,对象立即使用 toString() 方法转换为字符串。这样,规则1就被跳过了。普通的 JS 对象,{}或 new object(),通常被转换成 "[object Object]"
数组通过将它的元素与“,”分隔符连接转换为。例如 [1,3,"four"] 被转换成" 1,3,four"。
相等运算符 “==” 如果两个操作数不是同一类型,那么相等运算符会尝试一些类型转换,然后进行比较。
相等运算符算法(EEA)
例 1
1 == true // true
上面的转换步骤:
例 2
'' == 0 // true
上面的转换步骤:
例 3
null == 0 // false
上面的转换步骤:
例 4
null == undefined // true
上面的转换步骤:
例 5
NaN == NaN // false
上面的转换步骤:
例 6
[''] == '' // true
上面的转换步骤:
例 7
{} == true // false
上面的转换步骤:
即使在详细研究了本文中的所有示例、学习了算法之后,你会发现要立即理解复杂的比较还需要时间的积累。
告诉你一些技巧。 将本文添加到书签中(使用Ctrl + D),下一次看到有趣的情况时,可以根据等式算法编写逐步的计算。 如果检查至少 10 个示例,则以后不会有任何问题。
现在就可以试试,如 [0] == 0 的结果和转化步骤是什么?
相等运算符==进行类型转换。因此,可能会产生意想不到的结果,例如 {}== true 是 false( 参见例7)。在大多数情况下,使用全等操作符 === 更安全。
相等和全等运算符号可能是最常用的运算符之一。理解它们是编写稳定且bug较少的 JS 的步骤之一。
我们都知道通过Math.floor()方法可实现数值的向下取整,得到小于或等于该数字的最大整数。除了Math.floor方法,还可以使用位运算|,>>来实现向下取整哦
扩展运算符( spread )是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。
位运算的方法在其它语言也是一样的,不局限于JS,所以本文提到的位运算也适用于其它语言。位运算是低级的运算操作,所以速度往往也是最快的
平常的数值运算,其本质都是先转换成二进制再进行运算的,而位运算是直接进行二进制运算,所以原则上位运算的执行效率是比较高的,由于位运算的博大精深,下面通过一些在js中使用位运算的实例
js实现:四舍五入、向上取整、向下取整等方法。parseInt、Math.ceil、Math.round、Math.floor、toFixed等的使用
JS经常会遇到延迟执行的动作,并且失败后自动尝试,尝试N次之后就不再尝试的需求,今天刚好又遇到,于是写个闭包,以后不断完善继续复用。检查并计数第一个参数用来标记是尝试哪个动作的,第二个参数是最大尝试次数
大多数语言都提供了按位运算符,恰当的使用按位运算符有时候会取得的很好的效果。在我看来按位运算符应该有7个:& 按位与、| 按位或、^ 按位异或、~ 按位非
PHP取整数函数常用的四种方法:1.直接取整,舍弃小数,保留整数:intval(); 2.四舍五入取整:round(); 3.向上取整,有小数就加1:ceil(); 4.向下取整:floor()。
ECMAScript 中的相等操作符由两个等于号 ( == ) 表示,如果两个操作数相等,则返回 true。相等操作符会先转换操作数(通常称为强制转型),然后比较它们的相等性。
前端工作中经常遇到数字计算保留小数问题,由于不是四舍五入的方式不能使用toFixed函数,本文采用正则表达式匹配字符串的方式,解决对数字的向上或向下保留小数问题:
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!