1、在 == 运算中,undefined == null ,除此之外,这2 个数据不与任何其他数据相等
2、string 、 number 、与 boolean之间比较,如果2个数值的类型不同,可以把非number型转换成number型 (like Number(),not parseFloat()),再进行比较,(大小比较运算确实是这样,但等于和不等于比较不是,但是对于 js 的标量(这里“标量”的不准确且不负责提法是指 boolean 、string 、number ), 这样做也是没错的,把 true 作为1,false 作为 0,剩下另一个就是字符串了),例如 , "true" == true , 无论将 "true" 转 boolean 还是将 true 转 string ,都得不到正确结果, 将他们转换为 number 比较就能得到正确结果。
3、对象型数据(String、 Number、Boolean、object、Array、function 等等)与string 、number 、boolean类型比较,会使 用valueOf()、toString() 方法的返回值参与比较,对象与对象比较,只要类型不同就为false,不会调用valueOf() 和 toString(),事实上,任何对象型数据都只等于自己.
4、NaN属于number型,不与任何数据相等,包括他自身, !NaN == true , isNaN(Number(undefined)) == true
5、Infinity 首先属于number型,然后,Infinity 只等于Infinity
6、 注意if语句中的表达式的位置特殊性,不要把比较运算与逻辑运算(||、&&)混为一谈,逻辑运算也不要与布尔运算(运算元前面 加 ! )混为一谈,逻辑元算总是返回一个运算元,比较运算和布尔运算总是返回true/false. if 语句的条件表达式隐含一个布尔运算的效果: 将表达式运算结果 result 执行 !!result 得到 true/false .
7、逻辑运算中,判断为 false 的数据有:false、null、undefined、空字符串、0、NaN,其余数据都是true,任何对象型数据都是true,包括Boolean对象自身。逻辑运算中, && 优先于 ||,试比较:
3 || 0 && 2 ; //3 ,即 3||(0&&2) (3 || 0 ) && 2 ; //2
8、===运算中,先比较类型,后比较数值
9、在switch-case中,case 参数是区分类型的
10、 在大于、小于(>、>=、>==、<、<=、<==)比较运算中,两边的运算元都转换成数字,undefined 与任何其他数据(包括 null)进行大于、小于比较都是 false,( Number(undefined) is NaN ),而 null 则被转换成数字 0 后进行比较(在ECMASCRIPT规范中,不同类型的标量进行大于、小于比较时,是转数字比较的,只有数字,大小的含义才有存在的价值 ,字符串之间的比较也是进行 unicode 码的比较),因此会有:
null<=0; //true null>=0; //true null>0; //false null<0;//false null==0;//false undefined==null //true undefined<=null //false undefined>=null //false
再看数组:
[1]==[1]; //false 两个不同的对象 [1]>=[1]; //true, 转换成数字后比较 Number([1].valueOf().toString())==1
更权威的文档看这里(ECMASCRIPT):
http://bclary.com/2004/11/07/#a-11.8.5
undefined 不是关键字,在非全局环境下,undefined 可以被重定义
//test1 var undefined = 1; console.log('test1',undefined,typeof undefined); //全局环境下, undefined 不会被修改 //test2 (function(){ undefined = 2; //全局的undefined 不会被修改 console.log('test2',undefined,typeof undefined); })(); //test3 (function(){ var undefined = 3; //undefined 被重定义 console.log('test3',undefined,typeof undefined); })(); //test4 (function(x,undefined) { //该闭包内 undefined 被重定义了 console.log('test4',undefined,typeof undefined,arguments) console.log(undefined*2) // 8 }('a',4))
关于类型转换:
在对象型数据参与比较运算和算术运算(+、-、*、% 等)时,使用对象型数据的valueOf()方法的返回值参与运算(Date 对象看场景,有点不太一样),标量对象和时间对象的 valueOf() 返回值都是标量,其他对象的返回值都是 object/function 型,如果 valueOf() 得不到标量,则继续调用 toString() 方法,使用 toString() 的返回值参与运算,如果这两个方法返回的都不是标量(或 undefined、null),程序将报错。
日期对象在这里跟其他对象有点不同,日期对象参与的 “+” 和 "==" 运算将直接理解为字符串,会跳过valueOf() 直接调用toString返回string,如果得不到标量则继续尝试 valueOf(),而 Date 对象参与乘法运算仍是调用valueOf返回数字参与运算,这可能是从日期的实用意义来考虑的,日期数据主要是用于阅读。
在界面输出字符串时会直接调用 toString 方法,比如 alert(x), document.write(x),如果 toString() 返回的不是标量,则尝试 valueOf() ,仍然得不到标量则报错
对于 parseInt([1]) 这样的情况, 参数位置的数组将直接调用 toString() 方法,这是由于 parseInt() 函数(包括 parseFloat() 和上述的界面输出函数)的实现方式使然,这些函数期望接收到的参数类型是string,并非参数的数据类型自身的自动转换导致。
一些测试:
//Array var _arrToString = Array.prototype.toString; var _arrVal = Array.prototype.valueOf; Array.prototype.toString=function(){ console.log("Array.toString is called"); return _arrToString.call(this); }; Array.prototype.valueOf=function(){ console.log("Array.valueOf is called"); return _arrVal.call(this); }; [1]+2 //Array.valueOf is called , Array.toString is called parseInt([1]) //parseInt 期望接收 string 型参数,直接调用了 Array.toString Number([1]) //valueof toString 先后被调用 //Boolean var _arrToString = Boolean.prototype.toString; var _arrVal = Boolean.prototype.valueOf; Boolean.prototype.toString=function(){ console.log("Boolean.toString is called"); return _arrToString.call(this); }; Boolean.prototype.valueOf=function(){ console.log("Boolean.valueOf is called"); return _arrVal.call(this); }; 1+new Boolean(true); //Boolean.valueOf is called //object var tostr = Object.prototype.toString; var valof = Object.prototype.valueOf; Object.prototype.toString = function(){ console.log('Object.toString iscalled'); return tostr.call(this); } Object.prototype.valueOf = function(){ console.log('Object.valueOf is called'); return valof.call(this); } ({})== 1; // valueOf toString 先后被调用 ({})== ({}); // 这里 valueOf 和 toString 未被调用 //Date var valueof = Date.prototype.valueOf; var toString = Date.prototype.toString; Date.prototype.valueOf = function(){ console.log('valueof is called'); return valueof.call(this); } Date.prototype.toString = function(){ console.log('toString is called'); return toString.call(this); } new Date()+1; //toString is called new Date()*1; //valueOf is called new Date()==1;//toString is called new Date()>=1;//valueOf is called parseInt( new Date()); //toString is called Number( new Date()); //valueOf is called
// toString 的调用
var tostr = Array.prototype.toString; var valof = Array.prototype.valueOf; Array.prototype.toString = function(){ console.log('Array.toString iscalled'); return tostr.call(this); } Array.prototype.valueOf = function(){ console.log('Array.valueOf is called'); return valof.call(this); } var arr = [2]; alert(arr); //Array.toString iscalled var x = arr +1; //Array.valueOf is called ,Array.toString is called
由于 Number(undefined)===NaN , Number(null)===0 ,因此 undefined 参与的数字运算将得到NaN,而null将作为数字0参与运算。
前 ++ 和后++ 运算属于单目运算,运算元会转换成number型再参与运算: 'a'++ 和 ++'a' 都会得到NaN,因为Number('a')=NaN.
当+作为单目运算符时,表示“取正数”,如 alert(+'a'); //NaN ,alert(typeof(+'1')); //number
Number() 函数将8进制格式的字符串按十进制处理,去掉前导的0
alert(012==10); //true alert('012'==10); //false alert(012=='012');//false alert(09==9); //true ,不符合8进制数,作为 十进制数处理 alert(012==10); //true 符合8进制数 alert(Number(012));//10 ,(012).toString(10) 得 '10' alert(Number('012'));//12,没有按八进制处理而是去掉0,注意区别 parseInt('012') 在firefox 和IE8 中得到 10(最新版本的 firefox 也已经返回 12),但在 IE9、IE10 和chrome 中得到12 alert(0x12==18);//true alert('0x12'==18);//true alert(0x12=='0x12');//true alert('0x12'=='18');//false ,字符串的比较,没有发生数据类型转换 alert(Number(0x12));//18 alert(Number('0x12'));//18
parseInt 将字符串转换成十进制整数时,可以接受2 个参数,第二个参数用于申明传入的字符串的进制
parseInt('abc',16); // 2748 ,将16进制数 abc 转换成10进制
对应的,number 对象的toString 方法也可以接受1个参数表示按哪一种进制转换成字符串:
(2748).toString(16); //abc
Object 与标量 Number 、String 、Boolean及 Date 的构造器不同,
如果 obj 是对象,则有
obj === new Object(obj) === Object(obj)
Number 、String 、Boolean、 Date 构造器则每次 new 都返回一个新的对象,如果不使用new,则返回新建对象的 valueOf 的值
var x = new Number(); x=== new Number(x) //false x=== new Object(x) //true //=======test========= var x = new Number(1) x=== new Number(x) //false x=== new Object(x) //true x=== Object(x) //true x.constructor //function Number() { [native code] } Object(x).constructor //function Number() { [native code] } (new Object(x)).constructor //function Number() { [native code] } typeof(new Number("123")); //object typeof(Number("123")); //number, not object