说明: 本篇主要讨论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);//
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);//
console.log(10+true);//
var o1 = {};
console.log(10+o1);//10[object Object] 对象默认的valueOf方法返回的不是原始类型,所以会调用toString方法,而toString返回的是字符串,所以执行字符串连接
o1.toString = function(){
return true;
}
console.log(10+o1);//
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中的类型转换(二)的更多相关文章

  1. JavaScript中数据类型转换总结

    JavaScript中数据类型转换总结 在js中,数据类型转换分为显式数据类型转换和隐式数据类型转换. 1, 显式数据类型转换 a:转数字: 1)Number转换: 代码: var a = " ...

  2. JavaScript中的类型转换(一)

    前言 JavaScript是一种非常灵活的弱类型的语言,它的灵活性的一方面体现在其繁杂多样的类型转换.比如当JavaScript期望使用一个布尔值的时候(比如if语句中)你可以提供任一类型的值,Jav ...

  3. [翻译]解释JavaScript中的类型转换

    原文地址:JavaScript type coercion explained 类型转换是将值从一种类型转换为另一种类型的过程(比如字符串转换为数值,对象转换为布尔值,等等).任何类型,无论是原始类型 ...

  4. javascript中的类型转换,宽松相等于严格相等

    为了将值转换为基本类型值(string,number,boolean,null,undefined),抽象操作ToPrimitive会首先检查该值有没有valueOf()方法,如果有并且返回基本类型值 ...

  5. javascript中强制类型转换

    javascript开发过程中,强制类型转换一般发生在条件判断和==运算符.其他情况,发生的类型转换(与这两种情况也是基本类似,属于万变不离其宗的范畴),暂不讨论. == 双等运算符 考虑代码: a ...

  6. Javascript中的事件二

    <!------------------示例代码一---------------------><!DOCTYPE html PUBLIC "-//W3C//DTD XHTM ...

  7. 【你不知道的javaScript 中卷 笔记2】javaScript中的类型转换

    1.1 对象内部属性 [[Class]] 常见的原生函数: String() Number() Boolean() Array() Object() Function() RegExp() Date( ...

  8. javascript中数据类型转换

    转换为数字: parseInt():转换为整数型数值:从下标0开始判断,若为数值型则继续直到遇到非数值,返回前面的整数值: 小数点无效,若0开始为非数值则返回NaN: 转换空字符串会返回NaN: 能转 ...

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

    1:parseInt(string) : 这个函数的功能是从string的开头开始解析,返回一个整数 parseInt("123hua"); //输出 123 parseInt(& ...

随机推荐

  1. SQLServer基本函数

    1.字符串函数  长度与分析用 datalength(Char_expr) 返回字符串包含字符数,但不包含后面的空格 substring(expression,start,length) 取子串 ri ...

  2. coursera机器学习笔记-多元线性回归,normal equation

    #对coursera上Andrew Ng老师开的机器学习课程的笔记和心得: #注:此笔记是我自己认为本节课里比较重要.难理解或容易忘记的内容并做了些补充,并非是课堂详细笔记和要点: #标记为<补 ...

  3. MongoDB与衍生版的TokuMX对比

    为什么会出现TokuMX呢? 查阅大量的资料和翻阅一些大牛的博客发现,MongoDB作为nosql派别的一个典型非关系型数据库其实存在许多缺陷不足之处. 然后肯定就会有有人跳出来,来做一个衍生的东西, ...

  4. 烂泥:学习mysql数据库主从同步复制原理

    本文由秀依林枫提供友情赞助,首发于烂泥行天下. 说明本篇文章部分转载自互联网. MySQL的Replication(英文为复制)是一个多MySQL数据库做主从同步的方案,特点是异步复制,广泛用在各种对 ...

  5. Mac OSX下卸载Nodejs

    有时手贱看到新版本就升级,升级后发现一堆模块不能用了,心情好慢慢调,但也有调不好的时候,只能卸载重装低版本的node了. 我的机器环境如下 1. Mac OSX 10.10.3 2. node为0.1 ...

  6. ubuntu将命令写在一个文件里,执行文件,source命令

    source命令也称为“点命令”,也就是一个点符号(.).source命令通常用于重新执行刚修改的初始化文件,使之立即生效,而不必注销并重新登录.用法: source filename 或 . fil ...

  7. .NET导入导出Excel

    若是开发后台系统,ASP.NET MVC中总是涉及了很多导入导出Excel的问题,有的时候处理起来比较烦 如果能使用以下代码解决,就完美了 public class ReportModel { [Ex ...

  8. ZBrush中文版ZBrushCore震撼来袭

    北京时间2016年9月30日,Pixologic公司召开新闻发布会,宣布ZBrush精简版ZBrushCore正式发布.该版本不仅支持中文,还支持多国语言,包括法语.西班牙语等.简单点来说,ZBrus ...

  9. Zookeeper C API 指南三(回调函数)(转)

    2013-02-21 12:54 by Haippy, 9237 阅读, 0 评论, 收藏, 编辑 接上一篇<Zookeeper C API 指南二(监视(Wathes), 基本常量和结构体介绍 ...

  10. AC日记——数字统计 openjudge 1.5 41

    41:数字统计 总时间限制:  1000ms 内存限制:  65536kB 描述 请统计某个给定范围[L, R]的所有整数中,数字2出现的次数. 比如给定范围[2, 22],数字2在数2中出现了1次, ...