文章目录
零、说明
- 本文章的代码是使用Chrome和Firefox浏览器验证通过了,其他平台未验证;
- 为方便输出结果,示例都采用了一个console.log()的包装函数print();代码如下:
/*********工具函数:print(),用于输出对象
* null和undefined调用该函数会报错
*/
Object.defineProperty(Object.prototype, 'print', {
configurable: true, //定义为true,是为了防止重复定义时报错;省略的writable和enumerable,默认为false;
value: function() {
console.log(this);
}
})
一、类型的转换规则
1、原始值之间的类型转换
- 各种原始值和对象的类型:
var un = undefined;
var nu = null;
var bt = true;
var bf = false;
var num = 1;
var st = 'hello world';
var objbt = new Boolean(true);
var objbt2 = new Boolean(true);
var num1 = new Number(1);
var num2 = new Number(1);
(typeof unhh).print(); // undefined
(typeof un).print(); // undefined
(typeof nu).print(); // object
(typeof bt).print(); // boolean
(typeof bf).print(); // boolean
(typeof num).print(); // number
(typeof st).print(); // string
(typeof objbt).print(); // object
- 原始值转换为Boolean类型:undefined、null、数字(0,-0,NaN)、空字符;转换结果为false,其他都为true;
- 转换为数字:undefined、null、false和空字符为0,true为1;字符串开头是数字转换前面的所有数字;开头不是数字,转为为NaN
- 转换为字符串:比较简单,直接转换;这里面有个注意是:undefined、null、false和数字0转换为字符串,不为空;转换得到的字符串再转换为boolean类型,则为true,跟直接转换的结果不同。
1.1、字符串与数字之间的转换方法
- 数字转换为字符串的方法:固定小数、指数计数法、有效数位法
var n = 123456.789;
n.toFixed(0).print(); //123457
n.toFixed(5).print(); //123456.78900
n.toExponential(1).print(); //1.2e+5
n.toExponential(3).print(); //1.235e+5
n.toPrecision(3).print(); //1.23e+5
n.toPrecision(8).print(); //123456.79
- 字符串转换为数字:parseInt()和parseFloat()两种方法
2、 对象与原始值之间类型转换的规则
- 对象转换Boolean类型:无论什么对象,转换为Boolean类型,都为true;
- 对象转换为字符串类型:
- 如果对象具有toString()方法,则调用这个方法;如果这个方法返回一个原始值,JavaScript将这个值转换为字符串(如果本身不是字符串的话),并返回这个字符串结果;也就是说toString方法返回的为非字符串原始值,则进行两步转换。
- 如果对象没有toString()方法,或者这个方法并不返回一个原始值,那么JavaScript会调用valueOf()方法;如果存在这个方法,JavaScript就调用它;如果返回值为原始值,JavaScript将这个值转换为字符串(如果本身不是字符串的话),并返回这个字符串结果。
- 否则,toString()和valueOf()都不能得到原始值,这时它将抛出一个类型错误异常。
- 对象转换为数字类型:
- 如果对象具有valueOf()方法,且返回一个原始值,则JavaScript将这个原始值转换为数字(如果需要的话)并返回这个数字;
- 否则,如果对象具有toString()方法,并返回一个原始值,这JavaScript将这个原始值转换为数字(如果需要的话)并返回这个数字;
- 否则,JavaScript抛出这个异常。
3、 常见对象的toString()和valueOf()方法
3.1、Object对象
所有的对象如果没有定义自己的方法会继承这两个方法;也可以通过Object.prototype.toString.call(obj)来调用这两个方法。
- toString方法:返回[object class]字符串,并不能反应对象的实际内容,但可以得到对象的类名
- valueOf方法:返回对象本身,不是一个原始值
3.2、Boolean对象
- toString方法: 返回 ‘false’ 或 ‘true’这两个字符串之一;
- valueOf方法:返回 true和false这两个原始值之一;
3.3、String对象
- toString方法和valueOf方法一样,都是返回字符串本身
3.4、Number对象
- toString方法: 返回数字的字符串,如 “112”
- valueOf方法:返回数字本身:如 12
3.5 Date对象
- toString方法:返回表示日期的字符串;
- valueOf方法:返回数字原始值;表示从1970年1月1号0时到该日期对象的秒数;
3.6 Function对象
- toString方法:返回函数定义式的完整字符串。
- valueOf方法:返回对象本身。
var bf = new Boolean(false);
if (bf) bf.print(); // Boolean{ false };这说明在if判断中bf转换为true了
function f() {};
(typeof f).print(); //String { "function" }
Object.prototype.toString.call(null).print(); //String { "[object Null]" }
Object.prototype.toString.call(undefined).print(); //String { "[object Undefined]" }
var date = new Date();
date.toString().print(); //String { "Wed Mar 04 2020 10:10:55 GMT+0800 (China Standard Time)" }
date.valueOf().print(); //Number { 1583287855786 }
二、类型转换相关的运算及其转换规则
1、判断运算
判断运算会转换为Boolean类型;常见的判断运算是:if、for语句和while语句的条件语句。
2 恒等运算符===
相等的条件:
- 两个变量都为原始值
- 两个变量的类型相同,也就是typeof的结果
- 两者都不能为null或undefined
- 都为number的话,两者都不能为NaN
- 满足以上条件,两者的值相同
- 对象类型,都不满足第一个条件,只有两个对象是同一个对象的条件下才相等,也就是同一个对象的引用
3 ==和!=运算符
相等的条件,处满足===的条件外,以下情况也可以相等;
- 两者都为null或undefined中的一个
- 数字、字符串或布尔值直接的比较:先转换为数字类型再进行比较
- 对象与字符串比较,先转换为字符串再比较
- 对象与数字或布尔原始值比较,先转换为数字再比较
- 两个对象之间比较的结果跟===运算一致。
4 关系运算符 > < >= <=
比较操作的操作数只有为string或number类型才能进行真正的比较;
- 对象,如果valueOf()返回一个原始值,那么直接使用这个原始值,否则,使用toString()方法得到的原始值;两个方法都不成功,则TypeError
- 两个操作数都为string类型,则按照string的比较规则来比较
- 其中有一个不为string类型,则都转换为数字进行比较;如果转换得到NaN,那么所有比较结果都为false
- 两个对象,只要满足上面的转换条件也可以进行比较
var n1 = new Number(5);
var n2 = new String('12');
n2 > n1; //true
5 加法运算符
- Date对象通过toString方法进行转换;其他对象:如果valueOf()返回一个原始值,那么直接使用这个原始值,否则,使用toString()方法得到的原始值;两个方法都不成功,则TypeError
- 转换后的原始值,如果其中一个为字符串,另外一个也转换为字符串,再进行计算
- 否则,都转换为数字进行计算
6 其他算术运算符
- 对象,如果valueOf()返回一个原始值,那么直接使用这个原始值,否则,使用toString()方法得到的原始值;两个方法都不成功,则TypeError
- 得到的原始值都转换为number类型进行计算
三、总结
虽然JavaScript是一个弱类型的语言,但它的类型一样重要;弱类型只是方便了对象的表示方式;但以对象为参数的函数,其能处理的类型是有限的,编写健壮性的代码,其类型检查就很重要:
- 判断语句中的类型转换、等于和不等的判断很重要,这些都是为了让我们更好的识别对象的类型;
- 加法运算符的数据转换也很重要:在我们输出字符串时,将其他对象转换为字符串的类型转换使用很多。
- 关系运算符、其他算术运算符:如果对象不一样,强行进行转换,然后做比较和运算,不是良好的编程风格;在JavaScript中应该使用定义相应的命名函数来处理相关问题。