javascript 的比较运算与逻辑运算

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

 

posted @ 2012-11-29 02:09  ecalf  阅读(957)  评论(3编辑  收藏  举报