案例:
console.log([] == ![]);
结果:true
简单理解:
js在运算是会发生隐式数据类型转换,优先转换成适合计算的数据类型。相当于Number([]) == Number(![])
复杂理解:
复杂数据类型在运算的时候,优先使用底层的两个API发生数据转换
valueOf( ):返回对象的初始值;
toString( ):返回对象的字符串值;
字符串
var str1 = 'hello world 1';
var str2 = new String('hello world 2');
console.log(str1);//'hello world 1'
console.log(str2);//String {"hello world 2"}
console.log( str1.valueOf() );//'hello world 1'
console.log( str2.valueOf() );//'hello world 2'
console.log( str1.toString() );//'hello world 1'
console.log( str2.toString() );//'hello world 2'
数字
var num1 = 123;
var num2 = new Number(456);
console.log(num1);//123
console.log(num2);//Number {456}
console.log( num1.valueOf() );//123
console.log( num2.valueOf() );//456
console.log( num1.toString() );//'123'
console.log( num2.toString() );//'456'
布尔值
var boo1 = true;
var boo2 = new Boolean(false);
console.log(boo1);//true
console.log(boo2);//Boolean {false}
console.log( boo1.valueOf() );//true
console.log( boo2.valueOf() );//false
console.log( boo1.toString() );//'true'
console.log( boo2.toString() );//'false'
基本类型 String Number Boolean 的valueOf 返回原始值(该是字符串的返回字符串,该是数字的返回数字)
基本类型 String Number Boolean 的toString 返回字符串值
复杂数据类型:
数组:
var arr1 = [1,2,3];
var arr2 = new Array(4,5,6);
console.log(arr1);//[1, 2, 3]
console.log(arr2);//[4, 5, 6]
console.log( arr1.valueOf() );//[1, 2, 3]
console.log( arr2.valueOf() );//[4, 5, 6]
console.log( arr1.toString() );//'1,2,3'
console.log( arr2.toString() );//'4,5,6'
对象:
var obj1 = {a:123};
var obj2 = new Object({b:456});
console.log(obj1);//{a: 123}
console.log(obj2);//{b: 456}
console.log( obj1.valueOf() );//{a: 123}
console.log( obj2.valueOf() );//{b: 456}
console.log( obj1.toString() );//'[object Object]'
console.log( obj2.toString() );//'[object Object]'
函数:
var fun1 = function (){alert(123)}
var fun2 = new Function("alert('456')");
console.log(fun1);//ƒ (){alert(123)}
console.log(fun2);//ƒ anonymous() {alert('456')}
console.log( fun1.valueOf() );//ƒ (){alert(123)}
console.log( fun2.valueOf() );//ƒ anonymous() {alert('456')}
console.log( fun1.toString() );//'ƒ (){alert(123)}'
console.log( fun2.toString() );//'ƒ anonymous() {alert('456')}'
引用类型 Array Object Function 的valueOf返回自身
引用类型 Array Object Function 的toString返回对象的字符串值(数组是去掉中括号的字符串,对象固定是[object Object],函数是本身代码的字符串)
综上所述:
当对象发生数据类型转换时,底部代码类似于
var arr1 = [1,2,3];
console.log(arr1);
arr1.valueOf = function (){
return this;
}
arr1.toString = function (){
return '1,2,3';
}
console.log( arr1.valueOf() );//[1,2,3]
console.log( arr1.toString() );//'1,2,3'
首先调用valueOf(),如果不能转换成功,再调用toString();
当对象和基本类型进行运算时,会把对象想办法获得对象的基本类型值
后台会自动调用valueOf方法,希望得到对象的一个基本类型值
如果得不到想要的值,再调用toString方法
案例解析:
console.log( arr3 == !arr4 );//true
//右边非空数组计算为false
console.log( arr3 == false );
//左边空数组和基本类型计算,调用valueOf返回本身
//调用toString转换为‘’空字符串
console.log( '' == false );
//空字符串与false计算会将转换为数字类型,都是0
console.log( '' == 0 );
console.log( 0 == 0 );
//将以上步骤放在一起看
console.log( Number(arr3.valueOf().toString()) == Number(!Boolean(arr4)) );
另外我们在页面见到的所有元素本质上都是字符串,所以alert等方法调用时会转换为字符串,这样只调用了toString;
只有当发生对象和基本数据类型运算的时候才会先调用valueOf
以下方法都只会调用toString;
var arr5 =[1,2,3,4];
alert(arr5);//'1,2,3,4'
document.write(arr5);//'1,2,3,4'
box.innerText = arr5;//'1,2,3,4'
console.log( arr5 + ' abc123' );//[1,2,3,4] abc123
案例二
// 如何让 (a==1&&a==2&&a==3)为true?
var a = {
i: 1,
valueOf : function (){
console.log('valueOf...');
// return a;
return this;
// return this.i++
},
toString: function (){
console.log('toString...');
// return '[object Object]';
// return a.i++
return this.i++
}
}
对象和数字运算,调用valueOf得不到值,调用toString,第一次比较转换的字符串为1,第二次为2,第三次为3,所以为true;