JavaScript中的类型转换(二)

说明: 本篇主要讨论JavaScript中各运算符对运算数进行的类型转换的影响,本文中所提到的对象类型仅指JavaScript预定义的类型和程序员自己实现的对象,不包括宿主环境定义的特殊对象(比如浏览器定义的对象)

上一篇中讨论了JavaScript中原始类型到原始类型的转换,原始类型到对象类型的转换和对象类型到原始类型的转换,这里先提出一个问题

var a = undefined;
if(a){
    console.log(‘hello‘);
}else{
    console.log(‘world‘);
}
console.log(a == false);

以前我不对JavaScript的一知半解的时候,我以为上面的代码回先后输出‘world‘和‘true‘,但是经过执行代码,发现结果是‘world‘和‘false‘.undefined确确实实可以被转换为false,但是在使用==操作符对undefined和false两个值进行相等性比较时,由于两个操作数的类型不同,这里会发生类型转换,并且undefined并没有被转换为boolean类型然后跟false比较,所以本篇讨论下运算符对运算数类型转换的影响.

1.+(二元),==,!=,>,<,<=,>=

二元+运算符用于把两个数字相加或者连接两个字符串,所以该运算符期望的运算数类型为数字或者字符串。当运算数都是数字或者字符串时,结果是显而易见的,否则的话就会现对操作数进行类型转换,把操作数转换为数字或者字符串,然后进行数学相加或者连接字符串的运算。操作数会照下面的规则进行类型转换:

1.如果其中任一操作数是对象类型,先执行对象到原始类型的转换:对于Date对象,通过调用toString方法得到原始类型的值;对于其他对象,优先尝试valueOf方法,然后再尝试toString方法,如果valueOf和toString都无法得到原始类型的值,则会抛出异常

2.现在两个操作数都是原始类型了,如果其中一个操作数是字符串,则把另外一个原始类型的操作数转换成字符串,然后执行字符串连接运算

3.否则,把两个操作数都转换成数字进行数学加法运算

console.log(‘10‘+null);//10null
        console.log(‘10‘+undefined);//10undefined
        console.log(‘10‘+false);//10false
        console.log(‘10‘+true);//10true
        console.log(‘10‘+10);//1010
        var o1 = {};
        console.log(‘10‘+o1);//10[object Object] 对象默认的valueOf方法返回的不是原始类型,所以会调用toString方法
        o1.toString = function(){
            return ‘o1‘;
        }
        console.log(‘10‘+o1);//10o1
        o1.valueOf = function(){
            return null;
        }
        console.log(‘10‘+o1);//10null 对象现在有了一个返回原始类型的valueOf方法,不再调用toStringconsole.log(10+null);
        console.log(10+undefined);//NaN, undefinde转换成数字是Nan
        console.log(10+false);//10
        console.log(10+true);//11
        var o1 = {};
        console.log(10+o1);//10[object Object] 对象默认的valueOf方法返回的不是原始类型,所以会调用toString方法,而toString返回的是字符串,所以执行字符串连接
        o1.toString = function(){
            return true;
        }
        console.log(10+o1);//11
        o1.valueOf = function(){
            return null;
        }
        console.log(10+o1);//10 对象现在有了一个返回原始类型的valueOf方法,不再调用toString                var date = new Date;
        console.log(date + true);//Tue Aug 19 2014 10:32:49 GMT+0800 (中国标准时间)true
 

使用==运算符比较两个运算数的相等性时,如果两个运算数类型不一致,就会发生类型转换,转换时遵循以下规则

1.null和undefined是相等的

2.如果一个操作数是数字,另一个操作数是字符串,则把字符串转换成数字再进行比较

3.如果有布尔类型的操作数,把它转换成数字

4.如果其中一个操作数是对象类型,把对象类型转换成原始类型再进行比较.当把对象转换成原始值时,优先使用valueOf方法,其次使用toString方法,但是与+运算符一样,Date对象是个特例,Date对象调用toString方法

5.其余情况一律认为不想等

到这里可以解释本文开始提出的问题了,undefined与false进行==比较,false先被转换成数字0,然后与undefined比较,属于情况5,返回false

console.log(0 == null);//false
        console.log( 0 == undefined);// false
        console.log(0 == false);//true,false转换成0
        console.log(1 == true);//true,true转换成1
        console.log(true == ‘1‘);//true,true先转换成1,然后1转换成字符串‘1‘
        console.log(null == ‘null‘);//false,情况5
        var o = {};
        console.log(o == ‘[object Object]‘);//true,toString方法返回‘[object Object]‘
        o.valueOf = function(){
            return ‘1‘;
        };
        console.log(true == o);//true,true先转换为1,o先调用valueOf得到一个原始值‘1‘,数字与字符串比较,数字转换成字符串

对于!=运算符,结果总是与==运算符的结果相反

对于>,<(很萌有木有),<=,>=这四个比较运算符,期望的运算数类型与二元+一样,要么比较两个数字,要么比较两个字符串,如果运算数不全位数字或字符串,则会发生类型转换,转换的规则如下:

1.如果任一操作数是对象类型,则先后尝试valueOf方法和toString方法把对象转换成原始类型,需要注意的是这里Date不再做特殊处理了,与其他对象一样

2.经过第一步之后,两个操作数都是原始类型了,如果都是字符串,则进行字符串比较,如果都是数字,则进行数字比较

3.否则,把两个原始类型都转换成数字,然后进行比较

console.log(1 > null);//true,null->0
        console.log( 1 >= undefined);// false,undefined->NaN
        console.log(1 <= undefined);//false
        console.log(null > undefined) // false,null->0,undefinde->NaN
        console.log(null <= undefined)//false
        console.log(‘1‘ < true);//false,‘1‘->1,true->1
        console.log(‘1‘ > true);//false
        var o = {};
        o.toString = function(){
            return 10;
        };
        console.log(o > 9);//true, o->10
        console.log(o > ‘9‘)//true,o->10,‘9‘->9
        o.toString = function(){
            return ‘10‘;
        }
        console.log(o > 9);//true, o->‘10‘,‘10‘->10
        console.log(o > ‘9‘)//false,o->‘10‘
        o={};
        var o1={};
        console.log(o > o1);//o和o1都通过toString方法转换成了字符串,并且字符串内容是一致的
        console.log(o < o1);
        console.log(o >= o1);

2.+(一元),-(一元和二元),*,++,--

这几个运算符期望的运算数都是数字类型,所以当操作数类型不对时,会把操作数转换为数字

var a = ‘10‘;
        console.log(+a);//+10
        console.log(1 - a);//-9
        console.log(a++);//10,但是此时a的类型已经发生了变化,++和--都需要一个左值,所以++‘10‘是错误的
        console.log(typeof a);//输出number,a的类型已经改变
        a = ‘10‘;
        var o = {};
        o.toString = function() {
            return ‘10‘;
        }
        console.log(o++);//10,o->‘10‘->10
        console.log(typeof o);//number
        o = {};
        o.toString = function() {
            return ‘10‘;
        }
        o.valueOf = function(){
            return false;
        }
        console.log(++o);//1,优先使用valueOf方法
        console.log(typeof o);//number

3.总结

从本文的分析可以看出,JavaScript中的大部分运算符都只能对原始类型的操作数进行运算,其中一部分只能对数字类型进行运算,另一部分可以对数字和字符串类型进行运算,当进行运算时,运算数与预期的类型不相符合时,会通过先后调用valueOf和toString方法将对象类型转换为原始类型(需要注意Date对象的特殊性),然后再将原始类型转换为数字或者字符串.

JavaScript中的类型转换(二)

时间: 2024-11-07 01:17:52

JavaScript中的类型转换(二)的相关文章

JavaScript中的类型转换(一)

前言 JavaScript是一种非常灵活的弱类型的语言,它的灵活性的一方面体现在其繁杂多样的类型转换.比如当JavaScript期望使用一个布尔值的时候(比如if语句中)你可以提供任一类型的值,JavaScript会按照需要自行转换类型:当使用==操作符比较两个类型值的时候,也会对两个操作数按需进行转换,同样的事情也发生在使用+,>和<等操作符时.这些灵活繁杂的转换往往会使初学者不知所措,本文对JavaScript的类型转换做一个总结. JavaScript中的类型分类 JavaScript中

Javascript中数据类型转换那些事

在js中,总的来说数据类型分为两大类,一类是原始值类型的,一类是引用类型的.原始值类型的包括:字符串(String) .数字(Number) .布尔值(Boolean) 以及两个特殊的值 null 和 undefined .引用类型的主要是指对象,在js中,对象的范围很广,甚至有js中一切都是对象这样的说法.对象可以分为 对象(Object) 以及更具体的数组(Array) . 函数(Function) 等类型.要注意的是,js中typeof运算符返回的类型只有:sting.number.boo

JavaScript中数据类型转换总结

在js中,数据类型转换分为显式数据类型转换和隐式数据类型转换. 1, 显式数据类型转换 a:转数字: 1)Number转换: 代码: var a = "123"; a = Number(a); 注意: a)如果转换的内容本身就是一个数值类型的字符串,那么将来在转换的时候会返回自己. b)如果转换的内容本身不是一个数值类型的字符串,那么在转换的时候结果是NaN. c)如果要转换的内容是空的字符串,那以转换的结果是0. d)如果是其它的字符,那么将来在转换的时候结果是NaN. 2)pars

javascript中的类型转换(进制转换|位运算)

1:parseInt(string) : 这个函数的功能是从string的开头开始解析,返回一个整数 parseInt("123hua"); //输出 123 parseInt("123"); //输出 123 parseInt("12.3"); //输出 12 parseInt("hua"); //输出 Nan 2:另外parseInt()方法还有其他模式,就是可以把二进制.八进制.十六进制或其他任何进制的字符串转换成整数

javascript中数据类型转换

转换为数字: parseInt():转换为整数型数值:从下标0开始判断,若为数值型则继续直到遇到非数值,返回前面的整数值: 小数点无效,若0开始为非数值则返回NaN: 转换空字符串会返回NaN: 能转换为不同的进制:如:var a=parseInt("123",2);//返回结果为2进制 parseFloat():转换为小数:从下标0开始,只有10进制形式:若有第二个小数点则第二小数点无效后面全部舍弃, 返回前面值,若0开始为非数值则返回NaN:会忽略前导0:如:var b=parse

JavaScript中的类型转换

1.隐式类型转换 ①== 如果相等操作的两个变量不是同一类型,那么相等运算符会尝试进行一些类型转换: 如果一个是null,一个是undefined,则他们相等: 如果一个值是数字,另一个是字符串,先将字符串转换为数字,然后使用转换后的值进行比较: 如果一个是true,则将其转换为1再比较,如果其中一个是false,则将其转换为0再比较: 如果一个值是对象,另一个值是数字或字符串,则将对象转换为原始值,再进行比较.对象通过toString()或者valueOf()方法转为原始值.JS语言核心的内置

JavaScript中的类(二)

一些基本概念 在对象上创建新属性时属性上的configurable,writeable,enumerable默认值为true,value默认undefined 用Obejct.defineProperty()创建新属性时,默认为false _year前面的下划线表示只能通过对象方法访问的属性 在不能使用Object.defineProperty的对象方法中,可以使用__defineGetter__和__defineSetter__来实现 Object.getOwnPropertyDescript

JavaScript中的继承(原型链)

一.原型链 ECMAScript中将原型链作为实现继承的主要方法,基本思想是利用原型让一个引用类型继承另一个引用类型的属性和方法. 实例1: function SupType() { this.property = true; } SupType.prototype.getSupvalue = function() { return this.property; }; function SubType() { this.subproperty = false; } //原型对象等于一个类型的实例

带你玩转JavaScript中的隐式强制类型转换

正题开始前我想先抛出一个问题,==和===有什么区别?可能一般人会想,不就是后者除了比较值相等之外还会比较类型是否相等嘛,有什么好问的,谁不知道?!但是这样说还不够准确,两者的真正区别其实是==在比较的时候允许做强制类型转换,而===不允许.好了终于引出了今天的重点,我们平时肯定遇到过强制类型转换的时候,死活想不通为什么要这样转换(为什么这两个相等)的情况.那么下面我就以==为例,来说明一下其中强制类型转换的规则. 前提知识 JavaScript中的6大类型:undefined.null.boo