1 + 2obj + 1[] == ![] [null] == false
=== 和 ===== 叫做严格运算符,对象类型指向地址相同或原始类型( 数值、字符串、布尔值)值相同;==叫做相等运算符,类型不同会进行转化再比较,undefined、null相等,对象类型还是比较引用。==运算符将原始值和其包装对象视为相等,但===运算符将它们视为不等。所有obj.a==null(相当于obj.a=== null || obj.a ===undefined)。
相等运算符就是常常引起js隐式转换的坑货,它也常常出现在我们的面试题中,不过我们在现实开发中,为了避免不必要的问题要求使用严格运算符,但是了解还是很有必要的。
想要了解js隐式转换,就要先从三个知识点下手。
原始类型原始类型(基本类型、基本数据类型、原始数据类型)是一种既非对象也无方法的数据。在 javascript 中,共有7种:string,number,bigint,boolean,null,undefined,symbol (ecmascript 2016新增)。
falsy 值 (虚值)falsy 值 (虚值) 是在 boolean 上下文中认定为 false 的值,在javascript只有 七个 falsy 值。
false false 关键字0 数值 zero0n 当 bigint 作为布尔值使用时, 遵从其作为数值的规则. 0n 是 falsy 值.一个空字符串 (字符串的长度为零). javascript 中的字符串可用双引号 , 单引号 '', 或 模板字面量 `` 定义。null null - 缺少值undefined undefined - 原始值nan nan - 非数值特别要说明的是,除了这七个对象全是真值,如new number 和new boolean 都是真值。
let b = new boolean(false);if(b){//会执行到这里。}
四大转换规则tostring规则:其他类型的值转换为字符串类型的操作
null => nullundefined => undefinedtrue => true false=>false10 => 10 1e21=>1e+21[1,2,3] => 1,2,3object对象 => [object object] 其实是调用tostring方法toprimitive规则:对象类型数组转为原始类型的操作
当对象类型需要被转为原始类型时,它会先查找对象的valueof方法,如果valueof方法返回原始类型的值,则toprimitive的结果就是这个值如果valueof不存在或者valueof方法返回的不是原始类型的值,就会尝试调用对象的tostring方法,也就是会遵循对象的tostring规则,然后使用tostring的返回值作为toprimitive的结果date 是先tostring再valueof如果在tostring再valueof后都不能拿到原始类型,再判断相等、加减时就抛出uncaught typeerror: cannot convert object to primitive valuetonumber规则
null=> 0undefined => nan123=>123 12ssd=>nan =>0false => 0 true=>1数组、对象toprimitivetoboolean规则
js中七个falsy 值 (虚值) 为false,其他都为true隐式转换有了对上面知识点的认识,我们可以来一举拿下js隐式转换了。
== 的过程(优先换成数字、字符串)首先看==前后有没有nan,有的话都是返回false。nan不等于任何值,包括其本身布尔值会转成数字类型,true转成1,false转成0数字和字符串比较,字符串会转成数字undefined和null除了和undefined或null相等,和其他相比都是false数字或者字符串和对象相比,对象使用toprimitive规则转换。当两个操作数都是对象时,javascript会比较其内部引用,当且仅当他们的引用指向内存中的相同对象(区域)时才相等,即他们在栈内存中的引用地址相同。+的过程(优先换成字符串、数字)如果至少有一个操作数是对象,它会被转换成原始值(字符串,数字或布尔);转换之后,如果至少有一个操作数是字符串类型,第二个操作数会被转换成字符串,并且会执行连接。在其他的情况下,两个操作数都会转换成数字并执行算数加法运算。-的过程(转换成数字)这个就很简单了,全部用tonumber规则转换成数字检测学习成果我们根据以上所学看几个笔试题。如果你都知道结果,就不用看我的废解释了。
[] == [] [] == ![] [null] == false
第一个,==左右都是对象,比较引用地址,这个两个不同的实例,肯定不相等啊。第二个,!的优先级高于==,所以先 [] 是真值,求非当让是false了,转成数字0,==左是对象右是数字,对象使用toprimitive规则转换成,再用tonumber规则就转成0了,判断为相等。第三个,[null]toprimitive再tonumber规则就转成0,false也转成0。
var a = 1;var b = 3;var obj1 = { i:1, tostring:function() { return 1; }, valueof:function() { return 1; }};var obj2 = { i:1, tostring:function() { return 2; }};var obj3 = { i:1, valueof:function() { return 3; }};var obj = { i:1,};var obje = { i:1, valueof:function() { return []; }, tostring:function() { return {}; }};a+b a + obj a + obje a+obj1 a+obj2 a+obj3 b+obj1 b+obj2 b+obj3 a==obj2 a==obj1
这道题比较简单你只要熟练掌握我上面说的那几个知识点可以了。下面直接写出结果啦。
a + b //13a + obj //1[object object]a + obje //uncaught typeerror: cannot convert object to primitive valuea+obj1 //2a+obj2 //12a+obj3 // 4b+obj1 //31b+obj2 //32b+obj3 //“33”a==obj2 //falsea==obj1 //true
最后提一个比较奇葩的题目。
定义一个变量a,使得下面的表达式结果为true
a == 1 && a == 2 && a == 3
这里我简单提示下,a要是一个对象,重写valueof方法,让它每次隐式转换的时候,调用时i++。
valueof()在object上默认返回的是对象不是原始类型,它会再调用tostring。所以只要重写tostring也可以。
如果还是没有思路,你们可以去看下这道题的文章原文从一道面试题说起—js隐式转换踩坑合集。
推荐教程:《js教程》
以上就是前端笔试中的坑位-js隐式转换问题的详细内容。
