javascript隐式类型转换

对象的原始值

在javascript中存在很多隐式转换,有些时候我们需要获取对象的原始值,然后进行进一步的运算。
获取对象的原始值有两种转换模式,对象到字符串的模式和对象到数字的模式。
对象到字符串的模式:先调用toString方法,获取原始值,如果没有得到原始值,再调用valueOf方法获取原始值。
对象到数字的模式:先调用valueOf方法,获取原始值,如果没有得到原始值,再调用toString方法获取原始值。

  1. 这里说的转换模式其实是代表调用toString方法和valueOf方法的先后。
  2. 如果我们没有重写toString方法,其返回的是一个与对象相关的字符串。
  3. 如果我们没有重写valueOf方法,大多数时候其返回的就是对象本身,日期(Date)对象返回一个整数。

+

隐式转换规则:

  1. 日期(Date)对象采取对象到字符串的转换模式,除日期对象以外采用对象到数字的转换模式;
  2. 如果操作数中有字符串或者有对象的原始值为字符串,优先做字符串连接;
  3. 如果没有操作数中没有字符串或者对象的原始值不为字符串,转换为数字进行运算;
//1. 两个操作数均为字符串时,做字符串连接
console.log('1.');
console.log(typeof ('hello' + ' jack'),'hello' + ' jack');
//2. 当有一个操作数为字符串时(包括原始值为字符串的对象),将另外一个操作数转换为字符串
console.log('2.');
console.log(typeof ('123' + 4),'123' + 4);
console.log(typeof (true + '123'),true + '123');
console.log(typeof (undefined + '123'),undefined + '123');
console.log(typeof ([1,2,3] + '123'),[1,2,3] + '123');
//这里[1,2,3]的原始值为'1,2,3',做字符串连接
console.log(typeof ([1,2,3] + 123),[1,2,3] + 123);
//这里可以看到日期对象是先调用的toString方法
console.log(typeof ('当前时间: ' + new Date()),'当前时间: ' + new Date());
console.log(typeof (12345 + new Date()),12345 + new Date());
//3. 当操作数中没有字符串时,一律转换为数字就行运算
console.log('3.');
console.log(typeof (true + 123),true + 123);
console.log(typeof (true+undefined),true+undefined);
console.log(typeof (undefined + 123),undefined + 123);
console.log(typeof (true+false),true+false);

测试结果:
输入图片说明
通过对valueOf方法和toString方法进行重写,可以更直观的观察转换过程。

  //valueOf返回字符串'456'
  //toString返回字符串'123'
  var test1 = {
    toString:function(){
      console.log('调用了toString方法');
      return '123';
    },
    valueOf:function(){
      console.log('调用了valueOf方法');
      return '456';
    }
  }
  console.log('1.');
  console.log(typeof (test1+123),test1+123);
  //valueOf返回数字456
  //toString返回字符串'123'
  var test2 = {
    toString:function(){
      console.log('调用了toString方法');
      return '123';
    },
    valueOf:function(){
      console.log('调用了valueOf方法');
      return 456;
    }
  }
  console.log('2.');
  console.log(typeof (test2+123),test2+123);
  //valueOf返回对象{}
  //toString返回布尔值true
  var test3 = {
    toString:function(){
      console.log('调用了toString方法');
      return true;
    },
    valueOf:function(){
      console.log('调用了valueOf方法');
      return {};
    }
  }
  console.log('3.');
  console.log(typeof (test3+123),test3+123);

测试结果:
输入图片说明

  1. 第一个例子实际进行的运算是:'456'+123
  2. 第二个例子实际进行的运算是:456+123
  3. 第三个例子实际进行的运算是:true+123

-

隐式转换规则: 一律转换为数字进行运算,任意一个操作数为NaN,结果为NaN。
所有对象均采用对象到数字的转换模式获取原始值

  //一律转换为数字进行运算
  //1. 字符串
  console.log('1.');
  console.log(typeof ('hello' - ' jack'),'hello' - ' jack');
  console.log(typeof ('124' - '123'),'124' - '123');
  //2. 字符串和布尔值
  console.log('2.');
  console.log(typeof (true - '123'),true - '123');
  //3. 字符串和数字
  console.log('3.');
  console.log(typeof ('124' - 123),'124' - 123);
  //4. 数字和数字
  console.log('4.');
  console.log(typeof (123 - 3),123 - 3);
  //5. 数字和布尔值
  console.log('5.');
  console.log(typeof (true - 123),true - 123);
  //6. 布尔值和布尔值
  console.log('6.');
  console.log(typeof (true - false),true - false);
  //7. null和undefined
  console.log('7.');
  console.log(typeof (undefined - '123'),undefined - '123');
  console.log(typeof (null - 123),null - 123);
  //8. 对象
  //这里实际是:'1,2,3'-123
  console.log('8.');
  console.log(typeof ([1,2,3] - 123),[1,2,3] - 123);
  //这里实际是:'3'-'123'
  console.log(typeof ([3] - '123'),[3] - '123');
  //9.日期对象
  //这里可以看到日期对象采用对象到数字的模式转换为原始值
  console.log('9.');
  console.log(typeof (new Date()-1),new Date()-1);

测试结果:
输入图片说明

===

不进行隐式转换
如果类型不同,结果为false
如果类型相同,基本数据类型比较其值,对象类型比较其引用

  //不进行任何隐式转换
  //1. 类型不同结果为假
  console.log('1.');
  console.log(true === 1);
  console.log(null === undefined);
  console.log(1 === '1');
  console.log(true === 'true');
  console.log({} === true);
  //2. 类型相同,基本数据类型比较其值,对象类型比较其引用
  console.log('2.');
  console.log(true === true);
  console.log(true === false);
  console.log(1 === 1);
  console.log(1 === 2);
  console.log('hello' === 'hello');
  console.log('hello' === 'hell');
  //对象类型比较其引用
  console.log({} === {});
  var obj = {};
  var temp = obj;
  console.log(obj === temp);

测试结果:
输入图片说明

==

隐式转换规则:

  1. 如果类型相同,不进行隐式转换,基本数据类型比较其值,对象类型比较其引用
  2. null和undefined 相等,null和除undefined以外类型一律不相等,undefined和除null以外的类型一律不相等
  3. 如果操作数包含1个对象,Date对象采用对象到字符串的模式获取原始值,除Date对象以外采用对象到数字的模式获取其原始值,
  4. 数字和字符串比较,数字和布尔值比较,布尔值和字符串比较,一律转换为数字进行比较
  5. 如果转换过程中有NaN,值为假,NaN和其身不等。判断是否为NaN,需使用isNaN()方法
  //1. 操作数类型相同时,直接进行比较,结果与 === 比较的结果相同
  console.log("1.");
  console.log(123 == 123);
  console.log('hello' == 'hello');
  console.log(true == false);
  //2. null和 undefined,除此以外,null,undefined和其它数据类型相比较一律返回false
  console.log("2.");
  console.log(null == null);
  console.log(undefined == undefined);
  console.log(null == undefined);
  //这里要注意虽然null,'',false均为假值,但并不表示他们相等。
  console.log(null == '');
  console.log(null == false);
  //3. 数字和字符串,转换为数字
  console.log("3.");
  console.log(123 == '123');
  console.log(123 == '123a');
  console.log(0.123 == '0.123000');
  //4. 数字和布尔值,转换为数字
  console.log("4.");
  console.log(123 == true);
  console.log(1 == true);
  console.log(0 == false);
  //5. 布尔值和字符串,转换为数字
  console.log("5.");
  console.log('true' == true);
  console.log('1' == true);
  console.log('0' == false);
  //6. 有一个操作数为对象时,采用对象到数字的方式获取原始值,日期对象采用对象到字符串的方式获取原始值
  console.log("6.");
  console.log({} == 123);
  console.log({} == '[object Object]');
  console.log([9] == '9');
  //通过下面这个例子可以看到,日期对象采用对象到字符串的方法获取原始值
  console.log(new Date(1457463544064) == 'Wed Mar 09 2016 02:59:04 GMT+0800 (中国标准时间)');
  console.log(new Date(1457463544064) == 1457463544064);

测试结果:
输入图片说明

>,<,>=,<=

隐式转换规则:

  1. 如果有对象,将其转换为原始值,采用对象到数字的转换模式
  2. 如果两个操作数均为字符串,进行字符串的比较
  3. 如果只有一个字符串或没有字符串,转换为数字进行比较
  4. 如果转换的值出现NaN,结果为假。
  //1. 操作数中两个全为字符串时,进行字符串的比较
  console.log('1.');
  console.log('a'>'b');
  console.log('ad'<'abc');
  //2. 操作数中两个不全为字符串时,转换为数字进行比较
  console.log('2.');
  console.log(123>'45');
  console.log(true>'45');
  console.log(null>'-45');
  //3. 转换过程中出现NaN,结果为假
  console.log('3.');
  console.log(123>'122a');
  console.log(undefined>'-45');
  console.log('true'>'45');
  //4. 对象的原始值采用对象到数字的转换模式转换为原始值
  console.log('4.');
  console.log({}>='[object Object]');
  console.log({}>=123);
  console.log([9]>='123');
  //5. 日期对象同样采用对象到数字的方法获取原始值
  //转换为数字,可以看到这两个数字是不等的
  console.log(new Date(1457463544064),+new Date(1457463544064));
  console.log(new Date(1457463544063),+new Date(1457463544063));
  //转换为字符串,这两个字符串是相等的
  console.log(String(new Date(1457463544064)) == String(new Date(1457463544063)));
  //字符串比较结果为假
  console.log(String(new Date(1457463544064)) > String(new Date(1457463544063)));
  //字符串比较结果为假
  console.log(+new Date(1457463544064) > +new Date(1457463544063));
  //实际是进行的数字的比较
  console.log(new Date(1457463544064) > new Date(1457463544063));

测试结果:
输入图片说明

!

隐式转换规则:

  1. 假值:0,'',null,undefined,NaN, 转换为false
  2. 除假值以外的所有值,均转换为true
  //1. 假值
  console.log(!'');
  console.log(!0);
  console.log(!null);
  console.log(!undefined);
  console.log(!NaN);
  //2. 真值
  console.log(!'0');
  console.log(!{});
  console.log(![]);

测试结果:
输入图片说明

小结

  1. 隐式转换时,只有在'+'和'=='运算中,日期对象采用对象到字符串的模式获取原始值。其他时候一律采用对象到数字的模式获取原始值。
  2. 在'==='中是不进行任何隐式转换的,在'=='中,类型相同的情况下,也不进行隐式转换。
  3. '+'运算时,优先做字符串连接
  4. '>','<','>=','<=',优先做数字比较

转载于:https://my.oschina.net/maoji/blog/633987

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值