JS不同类型之间运算与转换
基本数据类型隐式转换:
隐式转换逻辑
如:“32”+32=“3232” "+"可以把数字转换为字符串 “+”可以理解为字符串拼接
“32”-32=0 “- * /”可以把操作数转换为数字 “-”可以理解为减法运算
把一个变量num变成数字:num-0;
把一个变量num变成字符串:num+' ';
不同类型的基础数据之间的加法,数据先转换为number,然后转换为string(如果有string类型数据参与运算)
null + undefined // 0+NaN null + false // 0+0 1 + true // 1+1 1 + '1' //'11';数字与字符串相加结果是字符串 1 + 2 + '3' //'33';(1+2)的结果然后与'3'相加;这里要把每一步加法单独拆开来看,否则变成和下面一样的结果了. 1 + (2 +'3') //'123';先运算2+'3',然后1+'23' 's' + null //'snull' 's' + undefined // 'sundefined' 's' + true //'strue' 1 + true + undefined + 's' // 1+1+NaN+'s'=2+NaN+'s'=NaN+'s'=‘NaNs’
数据前有加号‘+',可以让字符串转化为数字
+'1'+1 // 2
+'s'+2 // NaN
常用的原始类型之间的转换函数就是String()、Number()、Boolean()。
JS原始类型转换表
在 js中只有空字符串、数字0、undefined、null、false、NaN这六个值为假,其余均为真。
由于隐式转换只能转换原始值类型,如果转换对象等复杂类型需要用到valueOf()和toString()
判断字符串是不是数字字符串:isNaN(str);
实现对象转字符串以及对象转数字的方法:
该转换规则只适用于本地对象。什么是本地对象?本地对象也叫内置对象,就是JS标准规范定义的对象或类。比如Array、Object、function、data、global。还有一类对象叫宿主对象,就是要有一个宿生的对象和环境,在JS中宿主对象都是寄生在浏览器中的,在浏览器中才存在的对象,比如event、BOM、DOM。
本地对象都继承了两个转换方法:toString()与valueOf()
(1)对象到字符串的转换过程
原始(基本)类型:undefined、null、string、number、boolean
首先调用toString()方法,只有当toString不返回一个原始值的时候,才会调用valueOf()
toString()方法基本上所有对象都返回字符串。
toString()方法用在对象上面,比如function、array、object,返回的值都差不多,都是返回这个对象的源码,但是以字符串的形式表示。
var a=[1,2,'a']; var b=a.toString(); console.log(b);//1,2,a console.log(typeof(b));//string var fun=function(){ return 'hello world'; } var f=fun.toString(); console.log(f);//function(){return 'hello world';} console.log(typeof(f));//string
valueOf存在任意原始值,他就默认将对象转换为表示它的原始值。如果是复合值,和toString()一样,即返回本身,但是还是和toString()方法有区别的,toString()返回的是以字符串形式表示,valueOf()返回的是以对象的形式表示
var obj={name:'an'}; var obj1=obj.toString(); console.log(obj1);//[object Object] console.log(typeof(obj1));//string var obj2=obj.valueOf(); console.log(obj2);//{name: "an"}
(2)对象到数字的转换过程
首先调用valueOf(),如果返回原始值,将原始值转为数字并返回,valueOf()基本上所有的对象返回的都是对象,虽然先使用valueOf(),但实际上也是使用的toString()的方法。
如let a={ }; 转为数字
首先会调用a的valueOf()方法,如果结果不是原始类型,那么调用toString()方法;
a.valueOf()返回对象本身{ },不是原始类型,所以需要继续调用toString()方法;
a.toString()返回“[object,object]”,是一个字符串类型,即原始类型,所以接下来会调用Number(“[object,object]”),返回NaN;
不同类型之间的比较:
(1)Object与原始数据类型:需要Object转为原始类型;
(2)String与Boolean:需要两个操作数同时转为Number;
(3)String/Boolean与Number:需要String/Boolean转为Number;
(4)undefined与null:和所有其他值比较的结果都是false,他们之间==成立。
做题中遇到的问题:
console.log(([])?true:false);//true Boolean([]); //true
console.log(([]==false)?true:false);//true????为什么两个的结果不一样
对于[ ]==false
- 首先左边[ ]不是原始值类型,就会先调用valueOf()进行转换;[ ].valueOf() //[ ]
- 发现valueOf转换完之后,依然不是原始值类型,则继续用toString()转换;[ ].toString() // “ ”
- 转换完成之后就转为了原始值类型 “ ”;
- 下面继续用Number转换 Number(" ")==0
- 将右边false转为Number类型也为0;所以[ ]==0==false
![] //false; +[] // 0 +![] // 0 []+[] // "" {}+{}//"[object Object][object Object]" {}+[]//0 {a:0}+1 // 1 []+{}//"[object Object]" []+![]//"false" {}+[]//0 ![]+[] // "false" ''+{} //"[object Object]" {}+'' //0 []["map"]+[] //"function map() { }" []["a"]+[] // "undefined" [][[]] + []// "undefined" +!![]+[] //"1" +!![] //1 1-{} //NaN 1-[] //1 true-1 //0 {}-1 //-1 []==![] //true
如何使(a==1&&a==2&&a==3)为true?
这道题目主要考察的是js的隐式类型转换。
(1)改写a对象的valueOf()方法或者toString()方法。
首先,如果a是一个对象,我们在两个类型作比较时,执行a==首先会执行valueOf()方法,如果没有valueOf()方法就会去执行toString()方法。
原理:valueOf()第一次返回一个值,取过之后返回另一个值。
const a={ i:1, valueOf:()=>{ return a.i++; } } console.log((a==1)&&(a==2)&&(a==3));//true
实现(a+1<a)
const a={ i:0, valueOf:()=>{ return a.i+=2; } } console.log(a+1<a);//true
//通过valueOf()转换,使转化后的值为原来的a+2才会大于左边
(2)利用数组的特性
数组也是对象,做隐式转换时调用toString()方法返回一个字符串,该字符串有数组中的每个元素的toString()返回值经调用join()方法连接组成。所以可以看到数组的toString()会调用join方法,这里把自己的join()方法改写为shift()方法,每次返回第一个元素,而且删除原数组的第一个元素,正好使判断成立。
var b=[1,2,3]; b.join=b.shift; console.log(b==1&&b==2&&b==3);//true
JS判断空对象或者空数组的方法:
(1)判断空对象
首先判断参数是不是对象:Object.prototype.isPrototypeOf(obj) //true
1.JSON.stringify() :将对象转化为json字符串,再判断该字符串是否为"{}"
var obj1={}; var obj2={name:123}; function empty(obj){ var flag=JSON.stringify(obj); if(flag=='{}'){ return true; } else{ return false; } } console.log(empty(obj1));//true console.log(empty(obj2));//false
2.for循环
function empty(obj){ for(var key in obj){ return false; } return true; }
3、使用ES6的Object.keys()方法
function empty(obj){ var o=Object.keys(obj); return o.length==0 }
逻辑运算
(1)逻辑或( || ) 从字面上来说,只有前后都是false的时候才会返回false,否则返回true。
由上可知:
只要“||”前面为false,不管“||”后面是true还是false,都会返回“||”后面的值;
只要“||”前面为true,不管后面是true还是false,都会返回“||”前面的值。
(2)逻辑与(&&)从字面上将,只要前后都为true才为true
只要“&&”前面是false,无论“&&”后面是true还是false,结果都会返回“&&”前面的值;
只要“&&”前面是true,无论“&&”后面是true还是false,结果都将返回“&&”后面的值;